Skip to content

fix: exception on null embedded scalar values - #2896

Merged
bagerard merged 6 commits into
MongoEngine:masterfrom
efrederickson:patch-1
Aug 30, 2026
Merged

fix: exception on null embedded scalar values#2896
bagerard merged 6 commits into
MongoEngine:masterfrom
efrederickson:patch-1

Conversation

@efrederickson

Copy link
Copy Markdown
Contributor

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.

@bagerard bagerard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for the fix 👍

@bagerard
bagerard merged commit e05d9b5 into MongoEngine:master Aug 30, 2026
23 of 24 checks passed
@bagerard

Copy link
Copy Markdown
Collaborator

Merged this in upcoming 1.0, thanks for the fix.
Note that I'm also taking the opportunity to remove the Queryset.values_list(), since it's just an alias to .scalar()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants