【问题标题】:Django model relationship infos with on_delete property具有 on_delete 属性的 Django 模型关系信息
【发布时间】:2022-11-16 03:15:26
【问题描述】:

我想知道哪些模型是具有 on_delete 属性的模型的子项。据我所知,如果我们有 ownerModel,它是 childModel1check1Model 的父级,如下所示:

import uuid
from django.db import models

class ownerModel(models.Model):
    ownerId = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False, blank=True)

class check1Model(models.Model):
    checkId = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False, blank=True)
    owner=models.ForeignKey(ownerModel,on_delete=models.CASCADE)

class childModel1(models.Model):
    childId = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False, blank=True)
    check2=models.ForeignKey(ownerModel,on_delete=models.CASCADE)

然后我们可以用这样的代码得到哪些模型是ownerModel的孩子:

class myView(views.APIView):
    def get(self, request, format=None):
        for f in ownerModel._meta.get_fields():
            if 'field' in f.__dict__.keys():
                print('***childModels***')
                print(f.__dict__)
                print()
        return Response({'0000'}, status=status.HTTP_200_OK)

我的意思是检查 field 键是否在 __dict__.keys() 的项目中 ownerModel._meta.get_fields()

ofc 所以像这里我们得到关于儿童模型的扩展信息:

***childModels***
{'field': <django.db.models.fields.related.ForeignKey: owner>, 'model': <class 'Users.models.ownerModel'>, 'related_name': None, 'related_query_name': None, 'limit_choices_to': {}, 'parent_link': False, 'on_delete': <function 
CASCADE at 0x00000286550848B0>, 'symmetrical': False, 'multiple': True, 'field_name': 'ownerId', 'related_model': <class 'Users.models.check1Model'>, 'hidden': False}

***childModels***
{'field': <django.db.models.fields.related.ForeignKey: check2>, 'model': <class 'Users.models.ownerModel'>, 'related_name': None, 'related_query_name': None, 'limit_choices_to': {}, 'parent_link': False, 'on_delete': <function CASCADE at 0x00000286550848B0>, 'symmetrical': False, 'multiple': True, 'field_name': 'ownerId', 'related_model': <class 'Users.models.childModel1'>, 'hidden': False}

所以我发现这两个条件是获取子模型信息所必需的:

  1. 在子模型中确保子关系设置为如下一行:
    models.ForeignKey(ownerModel,on_delete=models.CASCADE)
    
    1. 如“如果 field 密钥在 ownerModel._meta.get_fields() 的项目中的 __dict__.keys() 中”,获取儿童信息。

    但问题是在某些情况下我无法从父模型中获取子信息。所以:

    1. 这让我想知道这两个条件是否足以找出哪些模型是模型的子模型?

    2. 还有其他类似的方法来获取哪些模型是模型的子代吗?

      顺便说一句,我也想拥有on_delete并且拥有on_delete是我使用_meta.get_fields()而不是_meta.fields的唯一原因,因为_meta.fields不提供on_delete属性。

      这是my code如果你想看一看。请注意,在完整的回答中,我也想知道是什么造成了问题,所以在这种情况下,__dict__.keys() 不提供其密钥中没有 field 的项目(不提供子模型详细信息)。因为通常这两个条件会提供子模型的详细信息。所以稍后我可以获得所有代码中的子模型详细信息。

【问题讨论】:

  • “使用on_delete 属性”是什么意思?所有且只有 ForeignKeyOneToOneField 字段将具有 on_delete 属性。你想找到所有依赖于这个模型的模型吗?只有外键和一对一还是多对多?

标签: django


【解决方案1】:

您可以使用Model._meta.related_objects找到模型的孩子

# Example Code
from django.utils.functional import classproperty
from django.db import models

class SomeModel(models.Model):
    class Meta:
        abstract = True
    
    @classproperty
    def related_objects(cls):
        """
        Return list of related models within the same module
        ManyToManyRel not supported
        """
        related_objects = [
            rel
            for rel in cls._meta.related_objects
            if isinstance(rel, (models.ManyToOneRel, models.OneToOneRel))
        ]
        return [
            (rel.related_model, rel.on_delete)
            for rel in related_objects
            if rel.related_model._meta.app_label == cls._meta.app_label
        ]

您可以将此类用作模型的 mro

【讨论】:

  • 我刚刚将 class Meta 部分和 @classproperty 添加到我现有的模型之一,并尝试获取 model1.related_objects 并返回 [] 空列表。顺便说一句,我也想拥有on_delete并且拥有on_delete是我使用_meta.get_fields()而不是_meta.fields的唯一原因,因为_meta.fields不提供on_delete属性。
  • 请检查您的代码,我已经更新了我的答案以包含on_delete
  • @Mike_Jones 谢谢,但我告诉过你,我只是将你的代码添加到我的一个班级中,然后打印 model1.related_objects 它返回 [](空列表)但应该返回孩子。
  • 也许这与 _meta.get_fields() 不起作用的原因相同
  • 也许这与 _meta.get_fields() 不起作用的原因相同
【解决方案2】:

如果你想检索到这个模型的反向关系,方法是ownerModel._meta.related_objects。然而,这是 Django 私有 API 的一部分,没有正式记录/支持。你还可以找到documentation in the source code

返回指向当前模型的所有相关对象。相关对象可以来自一对一、一对多或多对多字段关系类型。

私有 API 仅供 Django 自身使用; get_fields()结合字段属性的过滤是获取这个字段列表的公共API。

您还可以通过过滤get_fields()使用the public API获得类似的结果:

related_objects = [
    f for f in ownerModel._meta.get_fields(include_hidden=True)
    if (not f.hidden and (f.one_to_one or f.one_to_many)) or f.many_to_many
]

此解决方案还为您提供了在 ownerModel 中定义的多对多关系,如果您想要多对多,这很可能是预期的。要排除所有多对多关系,只需将它们从条件中删除:

related_objects = [
    f for f in ownerModel._meta.get_fields(include_hidden=True)
    if not f.hidden and (f.one_to_one or f.one_to_many)
]

一种仅严格获取向后关系(即删除 ownerModel 中定义的多对多关系)的方法可能是测试字段层次结构中 ForeignObjectRel 的存在。

from django.db.models.fields.reverse_related import ForeignObjectRel

related_objects = [
    f for f in ownerModel._meta.get_fields(include_hidden=True)
    if isinstance(f, ForeignObjectRel) and (not f.hidden or f.many_to_many)
]

如果您想要显示on_delete属性的值,您可以将结果限制为一对一和一对多字段。

related_objects = [
    f for f in ownerModel._meta.get_fields()
    if f.one_to_one or f.one_to_many
]
for f in related_objects:
    print(f, f.on_delete)

【讨论】:

    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 2018-11-03
    • 2011-12-09
    • 2019-04-25
    • 2012-08-27
    相关资源
    最近更新 更多