I’m new to Python and Django, so please be patient with me.
I have the following models:
class User(models.Model): name = models.CharField(max_length = 50) ... class Post(models.Model): userBy = models.ForeignKey(User, related_name='post_user') userWall = models.ForeignKey(User, related_name='receive_user') timestamp = models.DateTimeField() post = models.TextField() class Friend(models.Model): user1 = models.ForeignKey(User, related_name='request_user') user2 = models.ForeignKey(User, related_name='accept_user') isApproved = models.BooleanField() class Meta: unique_together = (('user1', 'user2'), )
I know that this may not be the best/easiest way to handle it with Django, but I learned it this way and I want to keep it like this.
Now, all I want to do is get all the post from one person and it’s friends. The question now is how to do it with the Django filters?
I think in SQL it would look something like this:
SELECT p.* FORM Post p, Friend f WHERE p.userBy=THEUSER OR ( (f.user1=THEUSER AND f.user2=p.userBy) OR (f.user2=THEUSER AND f.user1=p.userBy) )
With no guarantee of correctness, just to give an idea of the result I’m looking for.
from django.db.models import Q Post.objects.filter( \ Q(userBy=some_user) | \ Q(userBy__accept_user__user1=some_user) | \ Q(userBy__request_user__user2=some_user)).distinct()
Sorry, that was my fault. I didn’t pay attention to your
related_name values. See updated code above. Using
userBy__request_user alone won’t work because that’ll be a reference to
Friend which you can’t compare to to
User. What we’re doing here is following the reverse relationship to
Friend and then once we’re there, seeing if the other user on the friend request is the user in question.
This also illustrates the importance of describing reverse relationships appropriately. Many people make the same mistake you’ve made here and name the
related_name after the model they’re creating the FK to (
User), when actually, when we’re talking about reversing the FK, we’re now talking about
Friend. Simply, your related names would make more sense as something like: