Skip to content

Commit d71dad2

Browse files
committed
wip
1 parent 11754df commit d71dad2

File tree

3 files changed

+134
-11
lines changed

3 files changed

+134
-11
lines changed

django_mongodb_backend/fields/embedded_model.py

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,29 @@ def to_python(self, value):
8282
instance._state.adding = False
8383
return instance
8484

85-
def get_db_prep_save(self, embedded_instance, connection):
86-
"""
87-
Apply pre_save() and get_db_prep_save() of embedded instance fields and
88-
create the {field: value} dict to be saved.
89-
"""
90-
if embedded_instance is None:
85+
def get_db_prep_value(self, value, connection, prepared=False):
86+
if value is None:
9187
return None
92-
if not isinstance(embedded_instance, self.embedded_model):
93-
raise TypeError(
94-
f"Expected instance of type {self.embedded_model!r}, not "
95-
f"{type(embedded_instance)!r}."
96-
)
88+
89+
# if not isinstance(value, self.embedded_model):
90+
# raise TypeError(
91+
# f"Expected instance of type {self.embedded_model!r}, not "
92+
# f"{type(embedded_instance)!r}."
93+
# )
94+
95+
if not isinstance(value, self.embedded_model):
96+
return value
97+
98+
embedded_instance = value
99+
100+
# print(embedded_instance)
101+
# raise TypeError(
102+
# f"Expected instance of type {self.embedded_model!r}, not "
103+
# f"{type(embedded_instance)!r}."
104+
# )
105+
# Apply pre_save() and get_db_prep_save() of embedded instance
106+
# fields, create the field => value mapping to be passed to
107+
# storage preprocessing.
97108
field_values = {}
98109
add = embedded_instance._state.adding
99110
for field in embedded_instance._meta.fields:
@@ -108,6 +119,37 @@ def get_db_prep_save(self, embedded_instance, connection):
108119
embedded_instance._state.adding = False
109120
return field_values
110121

122+
def get_db_prep_save(self, value, connection):
123+
# """
124+
# Apply pre_save() and get_db_prep_save() of embedded instance fields and
125+
# create the {field: value} dict to be saved.
126+
# """
127+
if value is None:
128+
return None
129+
if not isinstance(value, self.embedded_model):
130+
raise TypeError(
131+
f"Expected instance of type {self.embedded_model!r}, not " f"{type(value)!r}."
132+
)
133+
134+
return super().get_db_prep_save(value, connection)
135+
# # Apply pre_save() and get_db_prep_save() of embedded instance
136+
# # fields, create the field => value mapping to be passed to
137+
# # storage preprocessing.
138+
# field_values = {}
139+
# add = embedded_instance._state.adding
140+
# for field in embedded_instance._meta.fields:
141+
# value = field.get_db_prep_save(
142+
# field.pre_save(embedded_instance, add), connection=connection
143+
# )
144+
# # Exclude unset primary keys (e.g. {'id': None}).
145+
# if field.primary_key and value is None:
146+
# continue
147+
# field_values[field.attname] = value
148+
# # This instance will exist in the database soon.
149+
# # TODO: Ensure that this doesn't cause race conditions.
150+
# embedded_instance._state.adding = False
151+
# return value # field_values
152+
111153
def get_transform(self, name):
112154
transform = super().get_transform(name)
113155
if transform:

tests/model_fields_/models.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,19 @@ class Author(models.Model):
119119
class Book(models.Model):
120120
name = models.CharField(max_length=100)
121121
author = EmbeddedModelField(Author)
122+
123+
124+
class Review(models.Model):
125+
title = models.CharField(max_length=255)
126+
rating = models.IntegerField()
127+
128+
def __str__(self):
129+
return self.title
130+
131+
132+
class Movie(models.Model):
133+
title = models.CharField(max_length=255)
134+
reviews = ArrayField(EmbeddedModelField(Review), null=True)
135+
136+
def __str__(self):
137+
return self.title

tests/model_fields_/test_embedded_model.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
Book,
1212
Data,
1313
Holder,
14+
Movie,
15+
Review,
1416
)
1517

1618

@@ -78,6 +80,64 @@ def test_pre_save(self):
7880
self.assertGreater(obj.data.auto_now, auto_now_two)
7981

8082

83+
class EmbeddedArrayTests(TestCase):
84+
def test_save_load(self):
85+
reviews = [
86+
Review(title="The best", rating=10),
87+
Review(title="Mediocre", rating=5),
88+
Review(title="Horrible", rating=1),
89+
]
90+
Movie.objects.create(title="Lion King", reviews=reviews)
91+
movie = Movie.objects.get(title="Lion King")
92+
self.assertEqual(movie.reviews[0].title, "The best")
93+
self.assertEqual(movie.reviews[0].rating, 10)
94+
self.assertEqual(movie.reviews[1].title, "Mediocre")
95+
self.assertEqual(movie.reviews[1].rating, 5)
96+
self.assertEqual(movie.reviews[2].title, "Horrible")
97+
self.assertEqual(movie.reviews[2].rating, 1)
98+
self.assertEqual(len(movie.reviews), 3)
99+
100+
def test_save_load_null(self):
101+
movie = Movie.objects.create(title="Lion King")
102+
movie = Movie.objects.get(title="Lion King")
103+
self.assertIsNone(movie.reviews)
104+
105+
106+
class EmbeddedArrayQueryingTests(TestCase):
107+
@classmethod
108+
def setUpTestData(cls):
109+
reviews = [
110+
Review(title="The best", rating=10),
111+
Review(title="Mediocre", rating=5),
112+
Review(title="Horrible", rating=1),
113+
]
114+
cls.clouds = Movie.objects.create(title="Clouds", reviews=reviews)
115+
reviews = [
116+
Review(title="Super", rating=9),
117+
Review(title="Meh", rating=5),
118+
Review(title="Horrible", rating=2),
119+
]
120+
cls.frozen = Movie.objects.create(title="Frozen", reviews=reviews)
121+
reviews = [
122+
Review(title="Excellent", rating=9),
123+
Review(title="Wow", rating=8),
124+
Review(title="Classic", rating=7),
125+
]
126+
cls.bears = Movie.objects.create(title="Bears", reviews=reviews)
127+
128+
def test_filter_with_field(self):
129+
self.assertCountEqual(
130+
Movie.objects.filter(reviews__title="Horrible"), [self.clouds, self.frozen]
131+
)
132+
133+
def test_filter_with_model(self):
134+
# print("start test")
135+
self.assertCountEqual(
136+
Movie.objects.filter(reviews=Review(title="Horrible", rating=2)),
137+
[self.clouds, self.frozen],
138+
)
139+
140+
81141
class QueryingTests(TestCase):
82142
@classmethod
83143
def setUpTestData(cls):
@@ -104,6 +164,11 @@ def test_nested(self):
104164
)
105165
self.assertCountEqual(Book.objects.filter(author__address__city="NYC"), [obj])
106166

167+
def test_with_dict(self):
168+
author = Author(name="Shakespeare", age=55, address=Address(city="NYC", state="NY"))
169+
obj = Book.objects.create(author=author)
170+
self.assertCountEqual(Book.objects.filter(author=author), [obj])
171+
107172

108173
@isolate_apps("model_fields_")
109174
class CheckTests(SimpleTestCase):

0 commit comments

Comments
 (0)