简体   繁体   中英

Django annotate queryset depending on another query

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?

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()

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM