Zikun Wang
Zikun Wang

Reputation: 21

Django related_name not working while using self reference in many-to-many field

I'm currently trying to create following relationship between users, so I used a many-to-many field in the User model to reference itself.

class User(AbstractUser):
    followers = models.ManyToManyField('self', related_name='following')

    def __str__(self):
        return self.username

However, when I tested this model using shell and trying to access the related_name, it reported error has occurred.

>>> u1 = User.objects.get(pk=1)
>>> u1.following.all()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'User' object has no attribute 'following'

Now I'm really confused, and really need help or alternative ways of doing this.

Upvotes: 2

Views: 3037

Answers (3)

YegorDB
YegorDB

Reputation: 41

Try this out https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.symmetrical.

It should looks like this

class User(AbstractUser):
    followers = models.ManyToManyField(
        'self',
        symmetrical=False,
        related_name='following',
    )

Upvotes: 4

Zikun Wang
Zikun Wang

Reputation: 21

I think the Django just doesn't allow us to give a related_name when the field is referencing itself.

For this specific task, I found this post is useful. Django models: database design for user and follower

What they essentially do is create another model called Following(), and use it to store the relationship.

class Following(models.Model):
    target = models.ForeignKey('User', on_delete=models.CASCADE, related_name = "followers")
    follower = models.ForeignKey('User', on_delete=models.CASCADE, related_name = "targets")

Upvotes: 0

Anoop
Anoop

Reputation: 543

if the Many to many relation is given to other models, the related_name attribute specifies the name of the reverse relation from the User model back to your model.

But in this case ..... both models are same

So you try this

u1 = User.objects.get(pk=1) u1.followers.all()

Upvotes: 0

Related Questions