﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34808	Some aggregation functions may return None; this isn't well documented	Eric Baumgartner	Lufafa Joshua	"Calls like Book.objects.filter(...).aggregate(Sum(""pages"")) may return None if the queryset is empty.

This isn't well documented and I think many of the examples in the documentation can lead to folks writing unsafe code that works most of the time, but can fail for empty queries.

For example (using models from https://docs.djangoproject.com/en/4.2/topics/db/aggregation/):

{{{#!python
obscure_publisher = ...
q = Book.objects.filter(publisher=obscure_publisher).Aggregate(Sum(""pages""))
total_pages = q[""pages""]  # None if the publisher hasn't published any books!

# Silly example, but will raise a TypeError
kilopages = total_pages / 1000
}}}

From what I've seen online, I think the safer approach is to use Coalesce.

{{{#!python
obscure_publisher = ...
q = Book.objects.filter(publisher=obscure_publisher).Aggregate(Coalesce(Sum(""pages""), 0)
total_pages = q[""pages""]  # Safe; using coalesce guarantees an int.
}}}

The only reference I've found to using Coalesce in this way appears to be a usage example at https://docs.djangoproject.com/en/4.2/ref/models/database-functions/#coalesce. Coalesce is not mentioned at all on the main aggregation page.

I think the documentation could be improved in a few ways.

On https://docs.djangoproject.com/en/4.2/topics/db/aggregation/:

- The code examples could consider adding Coalesce, or at least adding a comment at the top of the cheat sheet section mentioning that the examples do not include error checking and that using Coalesce is best practice.

For aggregation functions mentioned in https://docs.djangoproject.com/en/4.2/ref/models/querysets/:

- Add something to the documentation of the return type for functions used by aggregate() that mentions the empty queryset case if the result type differs for empty queries.
- For example, Count() safely returns an int even with empty querysets, but Sum, Avg, Min, and Max do not.
- Might also be worth mentioning that one can use Coalesce to avoid having to deal with None values.
"	Cleanup/optimization	closed	Documentation	4.2	Normal	fixed		Nick Pope	Accepted	1	0	0	1	0	0
