fix: exception on null embedded scalar values
Overview
When running a queryset like this:
values = set()
for results in MyModel.objects.filter(Q(a__subfield=1) | Q(b__subfield=1)).values_list("a__subfield", "b__subfield"):
values.update(results)
Over documents like this:
{"a": {"subfield": 1}, "b": {"subfield":1}},
{"a": {"subfield": 1}, "b": null},
{"a": {"subfield": 1}, "b": {"subfield":1}}
The method _get_scalar will raise an AttributeError on getting the attribute subfield of the second document where b is null.
The workaround currently is to instead do a values_list on (a, b) and then perform null checks on the client side, like this, which is much more verbose (assume get_value is a helper function roughly equivalent to getattr):
values = set()
for (a_par, b_par) in MyModel.objects.filter(Q(a__subfield=1) | Q(b__subfield=1)).values_list("a", "b"):
if a_par:
values.add(get_value(a_par, "subfield"))
if b_par:
values.add(get_value(b_par, "subfield"))
...
This is also less efficient as the whole embedded document must be fetched from the database instead of just the two desired fields. A similar solution using only could be utilized but it is also less elegant.
Fix
Add a simple null check into the _get_scalar method on BaseQuerySet, so that it returns None instead of raising an exception.