简体   繁体   English

Django通过表属性查询

[英]Django querying with Through table properties

I'm currently building a web application that will have a friends feature (eg Facebook, etc.). 我目前正在构建一个具有好友功能的Web应用程序(例如Facebook等)。

When a friend sends a friend request, a friendship object is created with accepted = False . 当朋友发送朋友请求时,将使用accepted = False创建一个友谊对象。 accepted is set to True when the requested friend accepts the request. 当所请求的朋友接受请求时, accepted设置为True

Here are my models (simplified greatly): 这是我的模型(大大简化了):

class Friendship(models.Model):
    sender = models.ForeignKey('Person', related_name='sender')
    receiver = models.ForeignKey('Person', related_name='receiver')
    accepted = models.BooleanField(default=False)

class Person(models.Model):
    person = models.OneToOneField(User)
    friends = models.ManyToManyField('self', through=Friendship)

I have it like this so I can also manage friend requests. 我这样子,所以我也可以管理朋友的请求。

Now let's say I have a person John. 现在,假设我有一个人约翰。 I want to get all of John's friends (eg, all friends that have accepted John's friend requests, and all friends whose friend requests John has accepted). 我想得到所有John的朋友(例如,所有接受John的朋友请求的朋友,以及所有其朋友请求John的朋友接受)。

Here's how I'm doing it now: 这是我现在的做法:

def friends(person):
    friends = Friendship.objects.filter(sender=person, accepted=True) | Friendship.objects.filter(receiver=person, accepted=True)
    friends = [friendship.sender for friendship in friends if friendship.sender != person] + \
              [friendship.receiver for friendship in friends if friendship.receiver != person]
    return friends

To me this seems really ugly and probably slow and inefficient. 在我看来,这似乎很丑陋,可能很慢且效率低下。 Does Django have some way of doing something like this? Django有做这种事情的方法吗?

def friends(person):
    return person.friends.filter(accepted=True)

Unfortunately this exact code doesn't work. 不幸的是,这个确切的代码不起作用。 Is there a better way? 有没有更好的办法?

I've had to run a very similar query recently. 我最近不得不运行一个非常相似的查询。 Something like this (or similar) should work: 这样的东西(或类似的东西)应该起作用:

def friends(person):
    friends = Person.objects.filter(Q(sender__receiver=person, sender__accepted=True) | Q(receiver__sender=person, receiver__accepted=True))
    return friends

You can do a join on a related field using the related_name attribute of the M2M Model, like Person.objects.filter(sender__accepted=True) 您可以使用M2M模型的Person.objects.filter(sender__accepted=True)属性在相关字段上进行Person.objects.filter(sender__accepted=True) ,例如Person.objects.filter(sender__accepted=True)

A "friend" is the other person in the Friendship relation. 友谊关系中的另一个人是“朋友”。 Ie if you are the receiver, the friend is the sender, and vice versa. 即,如果您是接收者,则朋友是发送者,反之亦然。 I'd also rename the related names "sender" and "receiver" and prepend "friend", so the above query is clearer. 我还将重命名相关的名称“发送者”和“接收者”,并在其前面加上“朋友”,因此上面的查询更加清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM