Как отфильтровать набор запросов по двум поискам в одном поле? - PullRequest
0 голосов
/ 26 ноября 2018

Я создаю приложение, похожее на трут.Вот модель представляет обзор от одного пользователя к другому:

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 голосов
/ 27 ноября 2018

Вы можете пересечь два QuerySets, используя функцию intersection или оператор & (QuerySet - это набор питонов), как описано здесь .

Так что если вы создадитедва 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 s, из которых на пересечении находятся совпадающие пользователи.flat=True требуется для создания двух списков, в противном случае ключи в каждом списке будут разными, а пересечение пустым:

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

или если вы просто хотите получить список идентификаторов:

match_ids = qs1 & qs2

Это дает вам всех пользователей, которые совпадают с request.user.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...