Skip to content

Commit 47221b4

Browse files
timgrahamWaVEV
authored andcommitted
field name validation
1 parent 11754df commit 47221b4

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

django_mongodb_backend/fields/embedded_model.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.core import checks
2+
from django.core.exceptions import FieldDoesNotExist
23
from django.db import models
34
from django.db.models.fields.related import lazy_related_operation
45
from django.db.models.lookups import Transform
@@ -112,7 +113,8 @@ def get_transform(self, name):
112113
transform = super().get_transform(name)
113114
if transform:
114115
return transform
115-
return KeyTransformFactory(name)
116+
field = self.embedded_model._meta.get_field(name)
117+
return KeyTransformFactory(name, field)
116118

117119
def validate(self, value, model_instance):
118120
super().validate(value, model_instance)
@@ -134,9 +136,25 @@ def formfield(self, **kwargs):
134136

135137

136138
class KeyTransform(Transform):
137-
def __init__(self, key_name, *args, **kwargs):
139+
def __init__(self, key_name, ref_field, *args, **kwargs):
138140
super().__init__(*args, **kwargs)
139141
self.key_name = str(key_name)
142+
self.ref_field = ref_field
143+
144+
def get_transform(self, name):
145+
result = None
146+
if isinstance(self.ref_field, EmbeddedModelField):
147+
opts = self.ref_field.embedded_model._meta
148+
new_field = opts.get_field(name)
149+
result = KeyTransformFactory(name, new_field)
150+
else:
151+
if self.ref_field.get_transform(name) is None:
152+
raise FieldDoesNotExist(
153+
f"{self.ref_field.model._meta.object_name}.{self.ref_field.name}"
154+
f" has no field named '{name}'"
155+
)
156+
result = KeyTransformFactory(name, self.ref_field)
157+
return result
140158

141159
def preprocess_lhs(self, compiler, connection):
142160
key_transforms = [self.key_name]
@@ -154,8 +172,9 @@ def as_mql(self, compiler, connection):
154172

155173

156174
class KeyTransformFactory:
157-
def __init__(self, key_name):
175+
def __init__(self, key_name, ref_field):
158176
self.key_name = key_name
177+
self.ref_field = ref_field
159178

160179
def __call__(self, *args, **kwargs):
161-
return KeyTransform(self.key_name, *args, **kwargs)
180+
return KeyTransform(self.key_name, self.ref_field, *args, **kwargs)

tests/model_fields_/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class Data(models.Model):
102102
integer = models.IntegerField(db_column="custom_column")
103103
auto_now = models.DateTimeField(auto_now=True)
104104
auto_now_add = models.DateTimeField(auto_now_add=True)
105+
json_value = models.JSONField(default=dict)
105106

106107

107108
class Address(models.Model):
@@ -119,3 +120,10 @@ class Author(models.Model):
119120
class Book(models.Model):
120121
name = models.CharField(max_length=100)
121122
author = EmbeddedModelField(Author)
123+
124+
125+
class Library(models.Model):
126+
name = models.CharField(max_length=100)
127+
books = models.ManyToManyField("Book", related_name="libraries")
128+
location = models.CharField(max_length=100, null=True, blank=True)
129+
best_seller = models.CharField(max_length=100, null=True, blank=True)

tests/model_fields_/test_embedded_model.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.core.exceptions import ValidationError
1+
from django.core.exceptions import FieldDoesNotExist, ValidationError
22
from django.db import models
33
from django.test import SimpleTestCase, TestCase
44
from django.test.utils import isolate_apps
@@ -104,6 +104,16 @@ def test_nested(self):
104104
)
105105
self.assertCountEqual(Book.objects.filter(author__address__city="NYC"), [obj])
106106

107+
def test_nested_not_exists(self):
108+
msg = "Address.city has no field named 'president'"
109+
with self.assertRaisesMessage(FieldDoesNotExist, msg):
110+
Book.objects.filter(author__address__city__president="NYC")
111+
112+
def test_not_exists_in_embedded(self):
113+
msg = "Address has no field named 'floor'"
114+
with self.assertRaisesMessage(FieldDoesNotExist, msg):
115+
Book.objects.filter(author__address__floor="NYC")
116+
107117

108118
@isolate_apps("model_fields_")
109119
class CheckTests(SimpleTestCase):

0 commit comments

Comments
 (0)