[Fixed]-How to update a queryset that has been annotated?

12👍

Without making a toy database to be able to duplicate your issue and try out solutions, I can at least suggest the approach in Django: Getting complement of queryset as one possible approach.

Try this approach:

qs.annotate(Count('book')).filter(Q(book__count__gt=1))
Work.objects.filter(pk__in=qs.values_list('pk', flat=True)).update(visible=False)
👤acjay

7👍

You can also clear the annotations off a queryset quite simply:

qs.query.annotations.clear()
qs.update(..)

And this means you’re only firing off one query, not one into another, but don’t use this if your query relies on an annotation to filter. This is great for stripping out database-generated concatenations, and the utility rubbish that I occasionally add into model’s default queries… but the example in the question is a perfect example of where this would not work.

👤Oli

2👍

To add to Oli’s answer: If you need your annotations for the update then do the filters first and store the result in a variable and then call filter with no arguments on that queryset to access the update function like so:

q = X.objects.filter(annotated_val=5, annotated_name='Nima')
q.query.annotations.clear()
q.filter().update(field=900)
👤söze

1👍

I’ve duplicated this issue & believe its a bug with the Django ORM. @acjay answer is a good workaround. Bug report: https://code.djangoproject.com/ticket/25171

Fix released in Django 2 alpha: https://code.djangoproject.com/ticket/19513

Leave a comment