如何通过相同字段的两次查找过滤查询集?

时间:2018-11-26 14:57:25

标签: django django-queryset

我正在构建类似火种的应用程序。这是一个代表从一个用户到另一个用户的评论的模型:

class Like(models.Model):
    like_from = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='outcome_likes')
    like_to = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='income_likes')
    is_positive = models.BooleanField()

created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return f'{self.like_from} -> {self.like_to}'

现在我正在尝试过滤所有匹配项,而我所拥有的就是以下代码:

def get_queryset(self):
    return CustomUser.objects.filter(income_likes__like_from=self.request.user, income_likes__is_positive=True)\
        .filter(outcome_likes__like_to=self.request.user, outcome_likes__is_positive=True)
    # I also tried to go from the opposite side but 
    # also had no idea how to get correct solution
    # Here should be some code to get intersection 
    # of these two querysets's values lists
    # positive_likes_from = self.request.user.income_likes.all().filter(is_positive=True).values('like_from')
    # positive_likes_to = self.request.user.outcome_likes.all().filter(is_positive=True).values('like_to')

但此处未注释的行将返回具有任何积极结果的用户,但不能保证将其发送给当前用户。 我想获得CustomUser模型的查询集,该查询集具有正的收入并且在另一侧当前用户喜欢的情况下获得类似的结果。 这是我的问题的解决方案,需要对数据库进行大量SQL查询:

def get_queryset(self):
    positive_likes_from = self.request.user.income_likes.all().filter(is_positive=True)
    positive_likes_to = self.request.user.outcome_likes.all().filter(is_positive=True)
    result = []
    for like in positive_likes_from:
        outcome_like_with_same_user_on_another_side = positive_likes_to.filter(like_to=like.like_from).first()
        if outcome_like_with_same_user_on_another_side:
            result.append((like, outcome_like_with_same_user_on_another_side))
    return result

1 个答案:

答案 0 :(得分:2)

您可以使用QuerySets函数或intersection运算符(QuerySet是python集)来将两个&相交,如here所述。

因此,如果您为传出的喜欢和传入的喜欢创建两个QuerySets

qs1 = self.request.user.income_likes.filter(is_positive=True).values_list('like_from', flat=True)
qs2 = self.request.user.outcome_likes.filter(is_positive=True).values_list('likes_to', flat=True)

您将拥有两个user_id列表,其中交集是匹配的用户。 flat=True需要创建两个列表,否则每个列表中的键将不同并且交集为空:

matches = CustomUser.objects.filter(id__in=qs1.intersection(qs2))

或者如果您只想要ID列表:

match_ids = qs1 & qs2

这将为您提供与request.user匹配的所有用户。