Django多个外键,相同的相关名称

时间:2018-08-23 14:30:48

标签: python django python-3.x django-models

我想创建一个模型(1),其中多个外键指向同一其他模型(2)。 我希望这些外键具有相同的related_name,因为每个外键都将指向model(2)的不同实例,因为所有外键都需要一个反向关系。

也许一个例子会更明确:

class Parent(Model):
    name = models.CharField(max_length=100)

class Child(Model):
    name = models.CharField(max_length=100)
    father = models.ForeignKey(Parent, related_name='children')
    mother = models.ForeignKey(Parent, related_name='children')

我该怎么做?

我已经知道这样做的丑陋方法:

class Parent(Model):
    name = models.CharField(max_length=100)

    @property
    def children(self):
         # Pick the existing one in fields 'children_1' or 'children_2'

class Child(Model):
    name = models.CharField(max_length=100)
    father = models.ForeignKey(Parent, related_name='children_1')
    mother = models.ForeignKey(Parent, related_name='children_2')

1 个答案:

答案 0 :(得分:5)

related_names不能相同,因为这会引起混乱:通过 mother相关的对象与对象完全不同。通过father相关。

您可以更改建模(例如,通过在ManyToManyField中引入Parent,例如在有关父母性别的关系中添加额外的数据)。但是这种方法的一个缺点是,现在您不再将关系的基数设置为2:这意味着Child可以(通过设计)拥有零个父母,一个父母,两个父母,三个父母或更多。此外,孩子可能有两个母亲,或两个父亲,或两个母亲和三个父亲。因此,它可能导致大量额外的逻辑来防止某些情况。请注意,在某些国家/地区是可能的:在某些国家/地区,可以将额外的人列为“父母”,他们与父母具有相同的合法权利和义务。

不过,您可以通过查询获取childrenChild为{{1的所有mother对象的查询来定义此类属性以获得father }}:

self

例如,您可以命名相关名称from django.db.models import Q class Parent(Model): name = models.CharField(max_length=100) @property def children(self): return Child.objects.filter(Q(mother=self) | Q(father=self))'father_of',以便您可以查询'mother_of'来获得some_parent.mother_ofsome_parent的孩子。例如,如果您想列出一个有母亲及其子女的表,或者如果您有可能mother_of改变性别的情况下进行申请,这可能很有用。

但是,如果您想使用严格的ParentFather,则定义两个分离模型可能会有所帮助。优点是您可以同时命名Mother related_name,然后根据设计检查'children'的{​​{1}}是否为男性(与father为女性相似)。