15

我想有一个ManyToMany与自身有关系的模型,我不知道怎么写,但我会尝试写一些代码来说明我想要做什么。

class Person(models.Model):
   name = models.CharField()
   occupation = models.CharField()

   friends = models.ManyToManyField('self', through = PersonFriends)

我希望朋友们通过的我的模型

class PersonFriends(models.Model)
   ???
   comment = models.CharField()

在具有直通关系ManyToMany的字段中,如果另一个模型的名称是“宠物”,例如,我将在该直通类中命名我的字段并将它们设为模型。例如_personpetForeignKey(Person)Pet

既然它们是相同的模型,我fields在我的模型中为两个人员字段命名我的名字是什么?PersonFriends

4

4 回答 4

23

你可以这样做:

class Person(models.Model):
    name = models.CharField(max_length = 255)
    occupation = models.CharField(max_length = 255)
    friends = models.ManyToManyField('self', through = 'PersonFriends', 
          symmetrical = False)
    #     ^^^^^^^^^^^
    # This has to be false when using `through` models. Or else your 
    # model will not validate.

class PersonFriends(models.Model):
    source = models.ForeignKey(Person, related_name = 'source')
    #                                  ^^^^^^^^^^^^
    # You need different `related_name` for each when you have 
    # multiple foreign keys to the same table. 

    target = models.ForeignKey(Person, related_name = 'target')
    comment = models.CharField(max_length = 255)
于 2010-10-07T10:08:11.510 回答
4

ManyToManyField.through_fields的官方文档中描述了所有内容(您可以在那里搜索“递归关系”短语以快速找到您需要的内容):

对于 django 1.11,您必须指定 through 和 (!) through_fields 参数:

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

    # note the additional arguments here
    friends = models.ManyToManyField(
        'self',

        # recursive relationships to self with intermediary
        # through model are always defined as non-symmetrical
        symmetrical=False,

        through='PersonFriend',

        # this argument is required to define a custom
        # through model for many to many relationship to self
        # position matters: 1 - source (from), 2 - target (to)
        through_fields=('person', 'friend'),        
    )


class PersonFriend(models.Model):
    # required relationship-defining foreign keys
    # (note that the order does not matter, it matters
    # in 'through_fields' argument in 'friends' field of the 'Person' model)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    friend = models.ForeignKey(Person, on_delete=models.CASCADE)

    # additional fields
    comment = models.CharField()
于 2017-07-01T20:35:03.817 回答
3

不假设友谊是对称的。因为巴斯光年可能是伍迪的朋友,但直到影片快结束,伍迪才和巴斯光年成为朋友。您可以简化这两个模型并且仍然具有合理的查找名称。你当然需要确保你定义了两个 PersonFriends 如果它是一个很好的友谊。

class Person(models.Model):
   name = models.CharField()
   occupation = models.CharField()

class PersonFriends(models.Model):
    from_person = models.ForeignKey(Person, related_name='friends_with')
    to_person = models.ForeignKey(Person, related_name='friends')
    comment = models.CharField()
    class Meta:
        unique_together = ('from_person', 'to_person')

这对于友谊的每个方向都有额外的评论。ie Tyrion 认为 Sansa 是一个可爱而聪明,但迷路的女孩。而珊莎可能会认为提利昂是一个丑陋但聪明善良的人。

于 2014-12-18T11:30:58.193 回答
2
class PersonFriends(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_person')
    to_person = models.ForeignKey(Person, related_name='to_person')

这是来自我的模型结构中与自我的多对多关系的 db 表结构。Django是这样定义的..

于 2010-10-07T10:05:03.587 回答