Reputation: 153
I am trying to make a Twitter clone.
The app has a series of users, each of which has a user profile. The UserProfile model is as follows
class UserProfiles(models.Model):
authenticated_user = models.OneToOneField(User, related_name="user_profile")
handle = models.CharField(max_length=50)
display_name = models.CharField(max_length=50)
following = models.ManyToManyField("self", related_name="followers", null=True)
def __str__(self):
return self.authenticated_user.handle
The "following" attribute is a many-to-many relationship with UserProfiles, as each user profile can follow many other profiles, and many profiles can be following another profile.
If I have an instance of UserProfiles, we'll call it current_user, I can find how many profiles it's following by doing
current_user.following.count
I also want to be able to tell the user how many people are following them. Since the related_name argument is set to "followers," it seems reasonable that I can get a count of followers by doing
current_user.followers.count
This, however, returns an error, "'UserProfiles' object has no attribute 'followers'"
Why won't what I did work? What can I do instead?
Upvotes: 2
Views: 517
Reputation: 19861
The default m2m relation to self is symmetrical in django. If you look at the documentation:
When Django processes this model, it identifies that it has a
ManyToManyField
on itself, and as a result, it doesn’t add aperson_set
attribute to thePerson
class. Instead, theManyToManyField
is assumed to besymmetrica
l – that is, if I am your friend, then you are my friend.If you do not want symmetry in many-to-many relationships with
self
, setsymmetrical
toFalse
. This will force Django to add the descriptor for the reverse relationship, allowingManyToManyField
relationships to be non-symmetrical.
In your case since symmetrical
attribute for the m2m relationship is true, it means:
A is following B => B is following A
But if you need both following
and followers
relationships you need to set symmetrical=False
:
following = models.ManyToManyField("self", related_name="followers",
symmetrical=False, null=True)
Upvotes: 2