如何将Djangos through_field设置为中间模型嵌套字段

时间:2016-05-18 06:30:42

标签: python django database-design django-models relational-database

有什么方法可以将through_field设置为中介模型的嵌套字段,

仅举例:

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',
        through_fields=('assignee__group', 'person'),
    )

class GroupLeader(models.Model)
      identity = models.ForeignKey(Person)
      group = models.ForeignKey(Group)  
      #more fields

class Membership(models.Model):
    assignee = models.ForeignKey(GroupLeader)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    # more fields

我尝试过这样做,但收到错误:

The intermediary model 'Membership' has no field 'assignee__group'

注意:以上只是一个示例,以防万一遇到这种情况。

1 个答案:

答案 0 :(得分:1)

您的小组负责人不应该成为M2M关系的一部分,这只是metadata。所以只需将group添加到Membership类。

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',
    )

class GroupLeaders(models.Model)
      identity = models.ForeignKey(Person)
      group = models.ForeignKey(Group)


class Membership(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    assignee = models.ForeignKey(GroupLeaders)

或者您甚至可以完全删除GroupLeaders

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',
        through_fields=('group', 'person'),
    )

class Membership(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    leader = models.ForeignKey(Person, on_delete=models.CASCADE,
        related_name="leading_memberships",
    )