问题
I'm trying to create an annotation on a queryset class that simply adds a boolean that is the result of some standard queries.
CustomQueryset(models.QuerySet):
""" An extension of the traditional queryset to support
filtering on accepting_offers """
def annotate_with_accepting_offers(self):
""" Add a lovely little variable to the SELECT that
says if the listing is accepting offers.
A <thing> is accepting offers when its:
+ not cancelled
+ expire date is today or in the future
+ has spaces left
"""
return self.annotate(accepting_offers=Q(cancelled=False) & Q(expire_date__gte=date.today()) & Q(spaces_left__gt=0))
def accepting_offers(self):
""" Annotate with 'accepting_offers' and filter the results that are True """
return self.annotate_with_accepting_offers().filter(accepting_offers=True)
def not_accepting_offers(self):
""" Annotate with 'accepting_offers' and filter the results that are False """
return self.annotate_with_accepting_offers().filter(accepting_offers=False)
This unfortunately does not work, any ideas what annotation would?
If this was SQL, the top line would look like:
SELECT *, (cancelled=False AND expire_date >= ? AND spaces_left > 0) AS accepting_offers
Edit: The reasons I intend on making this annotation is to make filtering on the variable easier, which you can see in the next two proceeding functions.
These two methods would be used within a larger chain of queries, so (ironically) keeping it simple with an annotation should help.
回答1:
As I mentioned in the comments, this isn't what Q expressions are for at all. I think what you want is a conditional expression:
return self.annotate(
accepting_offers=Case(
When(cancelled=False, expire_date__gte=date.today(), spaces_left__gt=0, then=Value(True)),
default_value=Value(False),
output_field=models.BooleanField()
)
)
来源:https://stackoverflow.com/questions/48488703/django-somehow-cannot-determine-simple-annotate-function