我发现一篇不错的文章讨论了前段时间,基础知识如下:
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)
注意related_name 末尾的加号。这向 Django 表明不应该暴露反向关系。由于关系是对称的,所以这是期望的行为,毕竟,如果我和 A 是朋友,那么 A 是我的朋友。 Django 不会为您创建对称关系,因此需要在 add_relationship 和 remove_relationship 方法中添加一些内容来显式处理关系的另一端:
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)
来源:Self-referencing many-to-many through