title: Django: using an annotated aggregate in queryset update()
body: <p>I've run into an interesting situation in a new app I've added to an existing project. My goal is to (using a Celery task) update many rows at once with a value that includes annotated aggregated values from foreign keyed objects. Here are some example models that I've used in previous questions:</p>
  
  <pre><code>class Book(models.model):
      author = models.CharField()
      num_pages = models.IntegerField()
      num_chapters = models.IntegerField()
  
  class UserBookRead(models.Model):
      user = models.ForeignKey(settings.AUTH_USER_MODEL)
      user_book_stats = models.ForeignKey(UserBookStats)
      book = models.ForeignKey(Book)
      complete = models.BooleanField(default=False)
      pages_read = models.IntegerField()
  
  class UserBookStats(models.Model):
      user = models.ForeignKey(settings.AUTH_USER_MODEL)
      total_pages_read = models.IntegerField()
  </code></pre>
  
  <p>I'm attempting to:</p>
  
  <ol>
  <li>Use the <code>post_save</code> signal from <code>Book</code> instances to update <code>pages_read</code> on related <code>UserBookRead</code> objects when a <code>Book</code> page count is updated.</li>
  <li>At the end of the signal, launch a background Celery task to roll up the <code>pages_read</code> from each <code>UserBookRead</code> which was updated, and update the <code>total_pages_read</code> on each related <code>UserBookStats</code> (This is where the problem occurs)</li>
  </ol>
  
  <p>I'm trying to be as lean as possible as far as number of queries- step 1 is complete and only requires a few queries for my actual use case, which seems acceptable for a signal handler, as long as those queries are optimized properly.</p>
  
  <p>Step 2 is more involved, hence the delegation to a background task. I've managed to accomplish most of it in a fairly clean manner (well, for me at least). </p>
  
  <p>The problem I run into is that when annotating the <code>UserBookStats</code> queryset with a <code>total_pages</code> aggregation (the <code>Sum()</code> of all <code>pages_read</code> for related <code>UserBookRead</code> objects), I can't follow that with a straight <code>update</code> of the queryset to set the <code>total_pages_read</code> field. </p>
  
  <p>Here's the code (the <code>Book</code> instance is passed to the task as <code>book</code>):</p>
  
  <pre><code># use the provided book instance to get the stats which need to be updated
  book_read_objects= UserBookRead.objects.filter(book=book)
  book_stat_objects = UserBookStats.objects.filter(id__in=book_read_objects.values_list('user_book_stats__id', flat=True).distinct())
  
  # annotate top level stats objects with summed page count
  book_stat_objects = book_stat_objects.annotate(total_pages=Sum(F('user_book_read__pages_read')))
  
  # update the objects with that sum
  book_stat_objects.update(total_pages_read=F('total_pages'))
  </code></pre>
  
  <p>On executing the last line, this error is thrown:</p>
  
  <pre><code>django.core.exceptions.FieldError: Aggregate functions are not allowed in this query
  </code></pre>
  
  <p>After some research, I found an existing Django ticket for this use case <a href="https://code.djangoproject.com/ticket/25643" rel="nofollow noreferrer">here</a>, on which the last comment mentions 2 new features in 1.11 that could make it possible.</p>
  
  <p>Is there any known/accepted way to accomplish this use case, perhaps using <code>Subquery</code> or <code>OuterRef</code>? I haven't had any success trying to fold in the aggregation as a <code>Subquery</code>. The fallback here is:</p>
  
  <pre><code>for obj in book_stat_objects:
      obj.total_pages_read = obj.total_pages
      obj.save()
  </code></pre>
  
  <p>But with potentially tens of thousands of records in <code>book_stat_objects</code>, I'm really trying to avoid issuing an UPDATE for each one individually.</p>