Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Changes in 1.0.0
``(changed_fields, unset_fields)`` tuple containing two disjoint lists of
database paths. ``_clear_changed_fields()`` was renamed to
``_clear_updated_fields()``.
- BREAKING CHANGE: Remove ``QuerySet.values_list()`` as it was just an alias to scalar. Use ``QuerySet.scalar()`` instead. #2931
- Add a warning that ``mongoengine.org`` is no longer controlled by the MongoEngine
project and appears to be an expired domain takeover.
- Bug Fix - Fix querying GenericReferenceField with __in operator #2886
Expand Down Expand Up @@ -66,6 +67,7 @@ Changes in 1.0.0
- Improve error message in case a document assigned to a ReferenceField wasn't saved yet #1955
- BugFix - Fix inc/dec atomic updates rejecting deltas outside a field's min_value/max_value #2339
- BugFix - Take `where()` into account when using `.modify()`, as in MyDocument.objects().where("this[field] >= this[otherfield]").modify(field='new') #2044
- BugFix: null embedded scalar values raises AttributeError #2896

Changes in 0.29.3
=================
Expand Down
6 changes: 2 additions & 4 deletions mongoengine/queryset/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,10 +1296,6 @@ def scalar(self, *fields):

return queryset

def values_list(self, *fields):
"""An alias for scalar"""
return self.scalar(*fields)

def as_pymongo(self):
"""Instead of returning Document instances, return raw values from
pymongo.
Expand Down Expand Up @@ -2023,6 +2019,8 @@ def lookup(obj, name):
chunks = name.split("__")
for chunk in chunks:
obj = getattr(obj, chunk)
if obj is None:
break
return obj

data = [lookup(doc, n) for n in self._scalar]
Expand Down
30 changes: 30 additions & 0 deletions tests/queryset/test_queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from mongoengine.queryset import (
DoesNotExist,
MultipleObjectsReturned,
Q,
QuerySet,
QuerySetManager,
queryset_manager,
Expand Down Expand Up @@ -4724,6 +4725,35 @@ class Person(Document):
("Gabriel Falcao", 23, "New York"),
]

def test_scalar_embedded_null_parents(self):
"""Test a multi-scalar query on embedded fields raises an exception when the parent field is null."""

class EmbeddedModelA(EmbeddedDocument):
designator = StringField()

class Container(Document):
source = EmbeddedDocumentField(EmbeddedModelA)
target = EmbeddedDocumentField(EmbeddedModelA, null=True)

# Create one with both values
Container(
source=EmbeddedModelA(designator="value1"),
target=EmbeddedModelA(designator="value2"),
).save()

# Create one with a null target, but the source value will match the query
Container(
source=EmbeddedModelA(designator="value1"),
target=None,
).save()

queryset = Container.objects.filter(
Q(source__designator="value1") | Q(target__designator="value2")
).scalar("source__designator", "target__designator")
# This should not raise an AttributeError on NoneType for the second Container's target__designator
values = list(queryset)
assert values == [("value1", "value2"), ("value1", None)]

def test_scalar_decimal(self):
from decimal import Decimal

Expand Down