Ошибка доступа к обратному полю manytomany от пользователя к связанной модели onetoone

У меня проблемы с классом модели, который имеет одностороннее отношение с моделью User, вот конфликтная часть:

class UserInteraction(models.Model):
    user = models.OneToOneField(User, related_name="interactions", on_delete=models.CASCADE)

    users_follows = models.ManyToManyField('self', through='UserFollow', blank=True, symmetrical=False, related_name='user_follows')
    users_likes = models.ManyToManyField('self', through='UserLike', blank=True, symmetrical=False, related_name='user_likes')

Когда я пытаюсь получить фолловеров/лайков, выполняя user.interactions.user_follows или user.interactions.user_likes, я получаю следующую ошибку:

In [18]: u = User.objects.get(id=1)

In [19]: u.interactions.users_likes.all()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [19], in <module>
----> 1 u.interactions.users_likes.all()

File ~\...\django\db\models\fields\related_descriptors.py:536, in ReverseManyToOneDescriptor.__get__(self, instance, cls)
    533 if instance is None:
    534     return self
--> 536 return self.related_manager_cls(instance)

File ~\...\django\db\models\fields\related_descriptors.py:826, in create_forward_many_to_many_manager.<locals>.ManyRelatedManager.__init__(self, instance)
    824     self.prefetch_cache_name = rel.field.name
    825     self.source_field_name = rel.field.m2m_field_name()
--> 826     self.target_field_name = rel.field.m2m_reverse_field_name()
    827     self.symmetrical = rel.symmetrical
    828 else:

File ~\...\django\db\models\fields\related.py:1598, in ManyToManyField._get_m2m_reverse_attr(self, related, attr)
   1596             setattr(self, cache_attr, getattr(f, attr))
   1597             break
-> 1598 return getattr(self, cache_attr)

AttributeError: 'ManyToManyField' object has no attribute '_m2m_reverse_name_cache'

Вот последователь и подобные модели, используемые для сквозного прохождения в fk:

class UserFollow(TimeStampBase):
    follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='follower')
    followed = models.ForeignKey(User, on_delete=models.CASCADE, related_name='followed')

    class Meta:
        constraints = [
            models.UniqueConstraint(
                name="%(app_label)s_%(class)s_unique_relationships",
                fields=["followed", "follower"],
            ),
            models.CheckConstraint(
                name="%(app_label)s_%(class)s_prevent_self_follow",
                check=~models.Q(follower=models.F("followed")),
            ),
        ]

    def __str__(self):
        return f'{self.follower} follows {self.followed}'


class UserLike(TimeStampBase):
    liker = models.ForeignKey(User, on_delete=models.CASCADE, related_name='liker')
    liked = models.ForeignKey(User, on_delete=models.CASCADE, related_name='liked')

    class Meta:
        constraints = [
            models.UniqueConstraint(
                name="%(app_label)s_%(class)s_unique_relationships",
                fields=["liked", "liker"],
            ),
            models.CheckConstraint(
                name="%(app_label)s_%(class)s_prevent_self_follow",
                check=~models.Q(liker=models.F("liked")),
            ),
        ]

    def __str__(self):
        return f'{self.liker} likes {self.liked}'

В админке все работает нормально, что я делаю не так?

Поля ForeignKey в сквозных моделях должны ссылаться на модель, содержащую поле ManyToManyField, а не на модель в поле OneToOneField - UserInteraction, а не User

class UserFollow(TimeStampBase):
    follower = models.ForeignKey(UserInteraction, on_delete=models.CASCADE, related_name='follower')
    followed = models.ForeignKey(UserInteraction, on_delete=models.CASCADE, related_name='followed')
    ...

class UserLike(TimeStampBase):
    liker = models.ForeignKey(UserInteraction, on_delete=models.CASCADE, related_name='liker')
    liked = models.ForeignKey(UserInteraction, on_delete=models.CASCADE, related_name='liked')
    ...
Вернуться на верх