3
class TradeItem(models.Model):
    ...

class Wishlist(models.Model):
    user = models.ForeignKey(User, related_name='wishlist_user')
    item = models.ForeignKey(TradeItem, related_name='wishlist_item')

I need to make TradeItem queryset annotated with a Boolean of whether an item is in this user's wishlist. Something like

items = TradeItem.objects.all().annotate(wishlist=
 <heresy>
 if Wishlist.objects.filter(user=request.user, item={current_item}: 
  True 
 else: 
  False
 </heresy>
 )

Is it possible to do the said thing with annotate/aggregate, and what would be the most efficient way for that in general?

2 Answers 2

4

You can actually solve this on database level in a single query, using Exists:

from django.db.models import Exists, OuterRef
user_wishlist = Wishlist.objects.filter(item_id=OuterRef('id'), user=user)
items = TradeItem.objects.annotate(in_wishlist=Exists(user_wishlist))

PS: I know, old question...

Sign up to request clarification or add additional context in comments.

Comments

3

The problem with this is that annotations are happening on database (SQL) level. You can only make use of functions which are nativly supported by the SQL dialect (like SUM, AVG...). If you want to append an arbitrary attribute/data field you should iterate over the queryset and check this for every instance seperatly:

items = TradeItem.objects.all()
user_wishlist = Wishlist.objects.filter(user=request.user)
for item in items:
    item.wishlist = user_wishlist.filter(item=item).exists()

2 Comments

Thank you, I started using your method, and it made my code neater. I sadly did not know that you can do qs.something = something , so terrible.
Iterating over a queryset might come with performance problems

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.