如何与django建立对称关系模型?

如何与django建立对称关系模型?,django,django-models,Django,Django Models,让我们以朋友为例 class Friendship(models.Model): user1 = models.ForeignKey(User, related_name='friends1') user2 = models.ForeignKey(User, related_name='friends2') handshakes = models.PositiveIntegerField() hugs = models.PositiveIntegerField()

让我们以朋友为例

class Friendship(models.Model):
    user1 = models.ForeignKey(User, related_name='friends1')
    user2 = models.ForeignKey(User, related_name='friends2')
    handshakes = models.PositiveIntegerField()
    hugs = models.PositiveIntegerField()
    # other silly data
友谊中的两个朋友(user1和user2)应该完全平等。我应该能够说(user1,user2)在一起是唯一的,不必担心(user2,user1)意外出现。我应该能够轻松地获得给定用户的所有朋友,但我必须编写一个自定义管理器或创建一些其他方式来获得关系中该用户为user1的所有朋友,以及该用户为user2的所有朋友


我正在考虑写我自己的SymmetricKey。有人请阻止我。

查看中
ManyToManyField
symmetric
选项--听起来它可以做你想做的事

对于你做这件事的具体方式,我会这样做

class LameUserExtension(User):
    friends = ManyToManyField("self", through=Friendship)

class Friendship(models.Model):
    # the stuff you had here

不久前,我发现一篇很好的文章讨论了这一点,基本内容如下:

class Person(models.Model):
    name = models.CharField(max_length=100)
    relationships = models.ManyToManyField('self', through='Relationship', 
                                           symmetrical=False, 
                                           related_name='related_to+')

RELATIONSHIP_FOLLOWING = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
    (RELATIONSHIP_FOLLOWING, 'Following'),
    (RELATIONSHIP_BLOCKED, 'Blocked'),
)

class Relationship(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_people')
    to_person = models.ForeignKey(Person, related_name='to_people')
    status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
请注意相关名称末尾的加号。这向Django表明不应公开反向关系。因为关系是对称的,这是我们想要的行为,毕竟,如果我是A个人的朋友,那么A个人就是我的朋友。Django不会为您创建对称关系,因此需要在add_关系和remove_关系方法中添加一点来显式处理关系的另一端:

def add_relationship(self, person, status, symm=True):
    relationship, created = Relationship.objects.get_or_create(
        from_person=self,
        to_person=person,
        status=status)
    if symm:
        # avoid recursion by passing `symm=False`
        person.add_relationship(self, status, False)
    return relationship

def remove_relationship(self, person, status, symm=True):
    Relationship.objects.filter(
        from_person=self, 
        to_person=person,
        status=status).delete()
    if symm:
        # avoid recursion by passing `symm=False`
        person.remove_relationship(self, status, False)
现在,每当我们创建一个单向的关系时,它的补充就被创建(或删除)。由于关系是双向的,我们可以简单地使用:

def get_relationships(self, status):
    return self.relationships.filter(
        to_people__status=status, 
        to_people__from_person=self)

来源:

+1对于“请阻止我”这一主题,这是一本很好的读物:我确实考虑过这一点,但听起来没有现在那么好。我真的不想使用多个模型来实现这一点,但我想这是一个不错的解决方案。哦,还要将我的标题改为“对称”,因为这是我的意思,不是自反性的。结果证明这是行不通的。在文档中:“当使用中间模型定义从模型到模型本身的多对多关系时,你必须使用symmetry=False”我知道这已经有好几年了,但这篇2009年的帖子不是告诉你如何做你想要的吗?还是我把问题搞错了?