Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django ORM查询用户的朋友_Django_Django Models_Orm - Fatal编程技术网

Django ORM查询用户的朋友

Django ORM查询用户的朋友,django,django-models,orm,Django,Django Models,Orm,我很难让Django ORM查询正常工作。我有这样的友谊模式: class Friendship(models.Model): user1 = models.ForeignKey(User, related_name='friendships1') user2 = models.ForeignKey(User, related_name='friendships2') class Meta: unique_together = ('user1', 'use

我很难让Django ORM查询正常工作。我有这样的友谊模式:

class Friendship(models.Model):
    user1 = models.ForeignKey(User, related_name='friendships1')
    user2 = models.ForeignKey(User, related_name='friendships2')
    class Meta:
        unique_together = ('user1', 'user2',)
为了找到一个给定用户的朋友,我们必须检查user1和user2,因为我们永远无法确定他们会站在关系的哪一边。因此,为了获得给定用户的所有好友,我使用以下查询:

user = request.user
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) |
    Q(friendships2__user1=user, friendships2__status__in=statuses)
)
在我看来,这似乎应该是可行的,但事实并非如此。它给了我副本。以下是它生成的SQL:

SELECT auth_user.*
FROM auth_user
LEFT OUTER JOIN profile_friendship ON (auth_user.id = profile_friendship.user1_id)
LEFT OUTER JOIN profile_friendship T4 ON (auth_user.id = T4.user2_id)
WHERE (
    (profile_friendship.status IN ('Accepted') AND profile_friendship.user2_id = 1 )
    OR (T4.user1_id = 1 AND T4.status IN ('Accepted'))
);
下面是我想要的SQL,它可以生成正确的结果:

SELECT f1.id as f1id, f2.id AS f2id, u.*
FROM auth_user u
LEFT OUTER JOIN profile_friendship f1 ON (u.id = f1.user1_id AND f1.user2_id = 1 AND f1.status IN ('Accepted'))
LEFT OUTER JOIN profile_friendship f2 ON (u.id = f2.user2_id AND f2.user1_id = 1 AND f2.status IN ('Accepted'))
WHERE f1.id IS NOT NULL OR f2.id IS NOT NULL

我知道我可以在一个原始查询中实现这一点,但我认为我无法链接。有没有一种干净的方法可以做到这一点而不必生吃?

你应该使用ManyToManyField.symmetric

简单解决方案:

user = request.user
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) |
    Q(friendships2__user1=user, friendships2__status__in=statuses)
).distinct()

有人知道有什么缺点吗?

他需要存储额外的信息,这似乎不起作用。@santiagobasulto或为M2M指定一个解决方案@santiagobasulto solution对我有效。但是,我想知道这个解决方案是否会更简单,甚至更好,只要我仍然可以指定一个直通表。然而,我不清楚如何在对称关系中做到这一点。我现在正试图弄明白……确认了这种方法不允许我指定一个直通表。错误:一个或多个模型未验证:accounts.profile:带有中间表的多对多字段不能对称。我测试了这个,它可以工作。就我个人而言,我不会完全按照ORM的方式编写查询,但它似乎仍然表现得相当好。这里唯一的缺点是,通过使用结果集中未包含的order by字段,可能会出现重复。