Skip to content

Commit 12a804f

Browse files
committed
INTPYTHON-602 Fix QuerySet results of embedded model fields that use database converters
1 parent 8804c87 commit 12a804f

File tree

5 files changed

+25
-1
lines changed

5 files changed

+25
-1
lines changed

django_mongodb_backend/fields/embedded_model.py

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.core import checks
44
from django.core.exceptions import FieldDoesNotExist
55
from django.db import models
6+
from django.db.models.expressions import Expression
67
from django.db.models.fields.related import lazy_related_operation
78
from django.db.models.lookups import Transform
89

@@ -78,6 +79,14 @@ def _resolve_lookup(_, resolved_model):
7879
model = property(lambda self: self._model, _set_model)
7980

8081
def from_db_value(self, value, expression, connection):
82+
if value is None:
83+
return None
84+
# Apply database converters to each field of the embedded model.
85+
for field in self.embedded_model._meta.fields:
86+
expression = Expression(output_field=field)
87+
converters = connection.ops.get_db_converters(expression)
88+
for converter in converters:
89+
value[field.attname] = converter(value[field.attname], expression, connection)
8190
return self.to_python(value)
8291

8392
def to_python(self, value):

docs/source/releases/5.1.x.rst

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ Django MongoDB Backend 5.1.x
1313
- Fixed the results of queries that use the ``tzinfo`` parameter of the
1414
``Trunc`` database functions.
1515
- Added support for ``QuerySet.dates()`` and ``datetimes()``.
16+
- Fixed loading of ``QuerySet`` results for embedded models that have fields
17+
that use database converters. For example, a crash for ``DecimalField``:
18+
``ValidationError: ['“1” value must be a decimal number.']``).
1619

1720
.. _django-mongodb-backend-5.1.0-beta-2:
1821

docs/source/releases/5.2.x.rst

+3
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ Bug fixes
3535
- Fixed the results of queries that use the ``tzinfo`` parameter of the
3636
``Trunc`` database functions.
3737
- Added support for ``QuerySet.dates()`` and ``datetimes()``.
38+
- Fixed loading of ``QuerySet`` results for embedded models that have fields
39+
that use database converters. For example, a crash for ``DecimalField``:
40+
``ValidationError: ['“1” value must be a decimal number.']``).

tests/model_fields_/models.py

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class Data(EmbeddedModel):
104104
auto_now = models.DateTimeField(auto_now=True)
105105
auto_now_add = models.DateTimeField(auto_now_add=True)
106106
json_value = models.JSONField()
107+
decimal = models.DecimalField(max_digits=9, decimal_places="2", null=True, blank=True)
107108

108109

109110
class Address(EmbeddedModel):

tests/model_fields_/test_embedded_model.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def test_pre_save(self):
9393
class QueryingTests(TestCase):
9494
@classmethod
9595
def setUpTestData(cls):
96-
cls.objs = [Holder.objects.create(data=Data(integer=x)) for x in range(6)]
96+
cls.objs = [Holder.objects.create(data=Data(integer=x, decimal=f"{x}.5")) for x in range(6)]
9797

9898
def test_exact(self):
9999
self.assertCountEqual(Holder.objects.filter(data__integer=3), [self.objs[3]])
@@ -113,6 +113,14 @@ def test_gte(self):
113113
def test_range(self):
114114
self.assertCountEqual(Holder.objects.filter(data__integer__range=(2, 4)), self.objs[2:5])
115115

116+
def test_exact_decimal(self):
117+
# EmbeddedModelField lookups call
118+
# DatabaseOperations.adapt__<foo>field_value().
119+
self.assertCountEqual(Holder.objects.filter(data__decimal="3.5"), [self.objs[3]])
120+
121+
def test_lt_decimal(self):
122+
self.assertCountEqual(Holder.objects.filter(data__decimal__lt="3"), self.objs[0:3])
123+
116124
def test_order_by_embedded_field(self):
117125
qs = Holder.objects.filter(data__integer__gt=3).order_by("-data__integer")
118126
self.assertSequenceEqual(qs, list(reversed(self.objs[4:])))

0 commit comments

Comments
 (0)