Django asymettrical self through relationship quer

2019-05-26 03:44发布

I have the following - simplified - models:

class User(models.Model):
    following = models.ManyToManyField("self", through='Following', symmetrical=False)

class Following(models.Model):
    from_user = models.ForeignKey(User, related_name='from_user')
    to_user = models.ForeignKey(User, related_name='to_user')
    status = models.IntegerField()

The status is 0 for pending, 1 for following Let user be a User. I would like to get all the followed users of user

I can do

user.following.all()

to get all the users user is following (pending relationships OR really follow)

or

Following.objects.filter(from_user=user, status=1)

to get all the Following objects with User user and real friendship

But how can I get all the User objects for user and status=1 ? I can't seem to find a way

Thank you !

2条回答
闹够了就滚
2楼-- · 2019-05-26 04:28

Try

user.following.filter(to_user__status=1)

the user.following is still querying on User, thus you need to span relation w/ __ to Follow here.

The two fields here, from_user and to_user, are both ForeignKey pointing to User model. Thus for an User() instance u:

  • u.following searches for the User()s who have relationship w/ u through the intermediate table, the Follow. The key here is that u.following picks the first ForeignKey in the Follow that points to the User, as the reference to u itself. Thus for your version of Follow, u.following.filter(to_user__status=1) filters on the Follow items having from_user equals to u and to_user w/ status equals to 1. The lookup is typical following relationship backwards
  • u.from_user searches the intermediate table for those having from_user equals to u
  • u.to_user searches the intermediate table for those having to_user equals to u

Also, you could filter on the ForeignKey directly, w/ remembering that the from_user and to_user are both ref the Follow:

User.objects.filter(to_user__from_user=user, to_user__status=1) # user as from_user
User.objects.filter(from_user__to_user=user, from_user__status=1) # user as to_user
User.objects.filter(following=user) # those who are followed by `to_user` user
查看更多
Viruses.
3楼-- · 2019-05-26 04:38

Seems that

user.following.filter(to_user__status=1)

does the trick. Can someone explain to me why, and how this works? user.following is a ManyRelatedManager which is querying on User. What would user.following.filter(from_user__status=1) do? Can't to guess what it returns... Thanks again !

查看更多
登录 后发表回答