我如何与Django建立对称关系?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (22)

让我们用典型的例子。

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

友谊中的两个朋友(user 1和user 2)应该是完全平等的。我应该可以说(user 1,user 2)是唯一的_在一起而不必担心(user 2,user 1)意外出现。我应该能够很容易地找到某个用户的所有朋友,但是我必须编写一个自定义管理器,或者创建一些其他方法来获得所有的友谊,其中用户在关系中是user 1,而在用户是user 2的所有友谊中。

我在考虑写我自己的对称键。谁来阻止我。

提问于
用户回答回答于

我发现了一篇很好的文章,讨论了不久前的基本知识如下:

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中。_关系与排除_关系方法显式处理关系的另一面:

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)
用户回答回答于

检查一下symmetrical任选ManyToManyField听起来它能做你想做的事

对于你的具体做法,我会做如下的事情

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

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

扫码关注云+社区