From dbeb2deb1f8b4a8d1f1431dad3e0a71940ed2504 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 31 May 2025 20:40:22 -0400 Subject: [PATCH 1/3] Reorder classes in forms/fields/embedded_model.py Match the order in embedded_model_array.py --- .../forms/fields/embedded_model.py | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/django_mongodb_backend/forms/fields/embedded_model.py b/django_mongodb_backend/forms/fields/embedded_model.py index bbfa9c02c..185be44bc 100644 --- a/django_mongodb_backend/forms/fields/embedded_model.py +++ b/django_mongodb_backend/forms/fields/embedded_model.py @@ -4,36 +4,6 @@ from django.utils.translation import gettext_lazy as _ -class EmbeddedModelWidget(forms.MultiWidget): - def __init__(self, field_names, *args, **kwargs): - self.field_names = field_names - super().__init__(*args, **kwargs) - # The default widget names are "_0", "_1", etc. Use the field names - # instead since that's how they'll be rendered by the model form. - self.widgets_names = ["-" + name for name in field_names] - - def decompress(self, value): - if value is None: - return [] - # Get the data from `value` (a model) for each field. - return [getattr(value, name) for name in self.field_names] - - -class EmbeddedModelBoundField(forms.BoundField): - def __init__(self, form, field, name, prefix_override=None): - super().__init__(form, field, name) - # prefix_override overrides the prefix in self.field.form_kwargs so - # that nested embedded model form elements have the correct name. - self.prefix_override = prefix_override - - def __str__(self): - """Render the model form as the representation for this field.""" - form = self.field.model_form_cls(instance=self.value(), **self.field.form_kwargs) - if self.prefix_override: - form.prefix = self.prefix_override - return mark_safe(f"{form.as_div()}") # noqa: S308 - - class EmbeddedModelField(forms.MultiValueField): default_error_messages = { "invalid": _("Enter a list of values."), @@ -79,3 +49,33 @@ def prepare_value(self, value): # (rather than a list) for initializing the form in # EmbeddedModelBoundField.__str__(). return self.compress(value) if isinstance(value, list) else value + + +class EmbeddedModelBoundField(forms.BoundField): + def __init__(self, form, field, name, prefix_override=None): + super().__init__(form, field, name) + # prefix_override overrides the prefix in self.field.form_kwargs so + # that nested embedded model form elements have the correct name. + self.prefix_override = prefix_override + + def __str__(self): + """Render the model form as the representation for this field.""" + form = self.field.model_form_cls(instance=self.value(), **self.field.form_kwargs) + if self.prefix_override: + form.prefix = self.prefix_override + return mark_safe(f"{form.as_div()}") # noqa: S308 + + +class EmbeddedModelWidget(forms.MultiWidget): + def __init__(self, field_names, *args, **kwargs): + self.field_names = field_names + super().__init__(*args, **kwargs) + # The default widget names are "_0", "_1", etc. Use the field names + # instead since that's how they'll be rendered by the model form. + self.widgets_names = ["-" + name for name in field_names] + + def decompress(self, value): + if value is None: + return [] + # Get the data from `value` (a model) for each field. + return [getattr(value, name) for name in self.field_names] From 525d960fdf48ab5b6c9529a814c22f2f56a1a4a7 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 31 May 2025 20:41:49 -0400 Subject: [PATCH 2/3] Document that embedded models don't have a primary key value --- docs/source/ref/models/models.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/ref/models/models.rst b/docs/source/ref/models/models.rst index a4491228a..32b5fc850 100644 --- a/docs/source/ref/models/models.rst +++ b/docs/source/ref/models/models.rst @@ -14,3 +14,6 @@ One MongoDB-specific model is available in ``django_mongodb_backend.models``. any of the normal ``QuerySet`` methods (``all()``, ``filter()``, ``delete()``, etc.) You also cannot call ``Model.save()`` and ``delete()`` on them. + + Embedded model instances won't have a value for their primary key unless + one is explicitly set. From 8c501aa63a22ca609739eae210172ebcb0456372 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 31 May 2025 20:43:02 -0400 Subject: [PATCH 3/3] Polished embedded model example --- docs/source/topics/embedded-models.rst | 53 ++++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/docs/source/topics/embedded-models.rst b/docs/source/topics/embedded-models.rst index 94abecfd2..0856c726f 100644 --- a/docs/source/topics/embedded-models.rst +++ b/docs/source/topics/embedded-models.rst @@ -10,41 +10,44 @@ The basics Let's consider this example:: - from django_mongodb_backend.fields import EmbeddedModelField - from django_mongodb_backend.models import EmbeddedModel + from django.db import models - class Customer(models.Model): - name = models.CharField(...) - address = EmbeddedModelField("Address") - ... + from django_mongodb_backend.fields import EmbeddedModelField + from django_mongodb_backend.models import EmbeddedModel - class Address(EmbeddedModel): - ... - city = models.CharField(...) + + class Customer(models.Model): + name = models.CharField(max_length=255) + address = EmbeddedModelField("Address") + + def __str__(self): + return self.name + + + class Address(EmbeddedModel): + city = models.CharField(max_length=255) + + def __str__(self): + return self.city The API is similar to that of Django's relational fields:: - >>> Customer.objects.create(name="Bob", address=Address(city="New York", ...), ...) - >>> bob = Customer.objects.get(...) - >>> bob.address - - >>> bob.address.city - 'New York' + >>> bob = Customer.objects.create(name="Bob", address=Address(city="New York")) + >>> bob.address + + >>> bob.address.city + 'New York' -Represented in BSON, Bob's structure looks like this: +Represented in BSON, the customer structure looks like this: .. code-block:: js - { - "_id": ObjectId(...), - "name": "Bob", - "address": { - ... - "city": "New York" - }, - ... - } + { + _id: ObjectId('683df821ec4bbe0692d43388'), + name: 'Bob', + address: { city: 'New York' } + } Querying ``EmbeddedModelField`` -------------------------------