I’ve got these models:
class User(AbstractUser):
friends = models.ManyToManyField('self', through='Friend')
friends_count = models.PositiveIntegerField(default=0)
followers_count = models.PositiveIntegerField(default=0)
class Friend(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_friends', related_query_name='user_friend')
friend = models.ForeignKey(User, on_delete=models.CASCADE, related_name='followers', related_query_name='follower')
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'friend'], name='unique_friend')
]
In a function based view I want to retrieve all the users except the logged in user:
users = models.User.objects.exclude(id=request.user.id)
In the template I want to list the users and add a follow or unfollow button depending on whether the logged in user already follows the user or not. I think I need to join the users with the friend objects where user_id is the id of the logged in user. I had a look at aggregation but wasn’t able to figure out how to get this right.
Kind regards.
Johanna
Is a “follow” the same as making an entry in Friend
?
If so, then one way to do this is to get a list of friends and check to see if the users you are iterating over are in that list or not.
In other words, for a given User
a_user
, then the list of friends is a_user.friends.all()
.
If other_user
is in a_user.friends.all()
, then other_user
is a friend
of a_user
. If other_user
is not in that list, then no such association exists.
Hi Ken,
Thanks for your reply.
Yes, follow is the same as making an entry into friend.
I had a look at the Queryset API again and wonder whether this could be done using
Based on the pizza example, I tried:
users = models.User.objects.annotate(has_friend=FilteredRelation('friends', condition=Q(friends__user_id=request.user.id)),).filter(has_friend__isnull=True)
This raises an error in the html file: Exception Value: Related Field got invalid lookup: user_id
The html files contains a simple {{ users }} tag. Comparing my code to the pizza example I don’t see what causes this error.
Kind regards,
Johanna
That’s because this clause:
Isn’t valid.
In a query, friends
is the reference to the table related by the many-to-many relationship and not a reference to the join table.
(If you wanted to reference the join table in the query, you would use the query_name, user_friend
.)
Django knows that when you’re referencing friends
in a query that it needs to build the join through the join table.
This means that what you need is friends__id=request.user.id
.
See the examples for Article and Publication at Many-to-many relationships | Django documentation | Django