Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django, in many to many relationship within the self class, how do I reference each other in terms of ORM?

class User(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    gender = models.IntegerField()
    email = models.CharField(max_length=100)
    password = models.CharField(max_length=255)
    following = models.ManyToManyField("self", related_name='followers')
    objects = UserManager()
    def __repr__(self):
        return "User: {0}".format(self.name)

In my model, User, users can follow and followed by each other.

I can find who the user is following by this:

user1 = User.objects.get(id=1)
following = user1.following.all()

However, I can't figure out how to find whom the user is followed by.

I tried:

user1.followers.all()

since it is the related_name in the following field in my model.

Can anybody please teach me how to do this?

Thank you very much.

like image 302
Jung Avatar asked Aug 23 '17 19:08

Jung


1 Answers

You should pass the symmetrical attribute to be False.

From the docs:

When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a followers attribute to the User class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your follower, then you are my follower.

If you do not want symmetry in many-to-many relationships with self, set symmetrical to False. This will force Django to add the descriptor for the reverse relationship, allowing ManyToManyField relationships to be non-symmetrical.

In your case:

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

Then in your views.py you can access both:

following = user.following.all()
followers = user.followers.all()

Since now the relationship with self is non-symmetrical.

like image 105
wencakisa Avatar answered Oct 20 '22 13:10

wencakisa