Как проверить в django модель ManyToManyField симметрично, если симметрично = False? - PullRequest
0 голосов
/ 05 февраля 2020

Я пытаюсь создать систему последователей в Django.

follows = models.ManyToManyField('self', related_name='follower', symmetrical=False, null=True, blank=True)

Поскольку система не должна быть симметричной, как я могу проверить, что два пользователя следуют друг за другом?

Я хочу иметь функцию в модели, если возможно. Я мог бы использовать эту функцию в limit_choices_to другого поля и некоторых других местах.

Первоначально я думал добавить поле «друзья» и сделать его симметричным, но позже это может привести к другим проблемам.

1 Ответ

0 голосов
/ 12 февраля 2020

Я не нашел простого решения, которое не потребует дополнительных моделей. Вот что я сделал:

Создание Person(models.Model) не требуется, если у вас реализовано что-то вроде CustomUser(AbstractUser). В противном случае класс Person может быть полезен во многих ситуациях.

count_ функции довольно полезны, но не нужны в большинстве случаев использования.

Внутри accounts/models.py Я добавил:

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

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

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

    def get_related_to(self, status):
        return self.related_to.filter(
            from_people__status=status,
            from_people__to_person=self)

    def get_following(self):
        return self.get_relationships(RELATIONSHIP_FOLLOWING)

    def get_followers(self):
        return self.get_related_to(RELATIONSHIP_FOLLOWING)

    def count_following(self):
        return len(self.get_relationships(RELATIONSHIP_FOLLOWING))

    def count_followers(self):
        return len(self.get_related_to(RELATIONSHIP_FOLLOWING))

    def get_friends(self):
        return self.relationships.filter(
            to_people__status=RELATIONSHIP_FOLLOWING,
            to_people__from_person=self,
            from_people__status=RELATIONSHIP_FOLLOWING,
            from_people__to_person=self)

    def count_friends(self):
        return len(self.get_friends())

class Relationship(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_people', on_delete=models.CASCADE)
    to_person = models.ForeignKey(Person, related_name='to_people', on_delete=models.CASCADE)
    status = models.IntegerField(choices=RELATIONSHIP_STATUSES)

    def add_relationship(self, person, status):
        relationship, created = Relationship.objects.get_or_create(
            from_person=self,
            to_person=person,
            status=status)
        return relationship

    def remove_relationship(self, person, status):
        Relationship.objects.filter(
            from_person=self,
            to_person=person,
            status=status).delete()
        return
...