Reputation: 5428
I'm building a tinder-like app. Here is a model represents review from one user to another:
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}'
Now I'm trying to filter all matches and all I have is this code:
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')
But uncommented line here will return users that have any positive outcome likes with no guarantee that they will be addressed to the current user.
I want to get a queryset of CustomUser
model that have positive income and outcome likes with a current user on another side.
Here is an solution of my problem that requires tons of SQL queries to the database:
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
Upvotes: 0
Views: 549
Reputation: 20672
You can intersect two QuerySets
using the intersection
function or the &
operator (a QuerySet is a python set) as described here.
So if you create two QuerySets
for the outgoing likes and incoming likes:
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)
you'll have two lists of user_id
s of which the intersection are the users that match. The flat=True
is required to make two lists otherwise the keys in each list would be different and the intersection empty:
matches = CustomUser.objects.filter(id__in=qs1.intersection(qs2))
or if you just want the list of ids:
match_ids = qs1 & qs2
This gives you all the users that have a match with the request.user
.
Upvotes: 2