[Django] #36986: Add a hook to Serializer._value_from_field() for complex fields like CompositePrimaryKey

8 views
Skip to first unread message

Django

unread,
Mar 13, 2026, 7:38:25 PM (5 days ago) Mar 13
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Type:
| Cleanup/optimization
Status: new | Component: Core
| (Serialization)
Version: dev | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
The Python serializer's `_value_from_field()` method using `isinstance`
for
[https://github.com/django/django/blob/main/django/core/serializers/python.py#L43-L44
special-case handling] of `CompositePrimaryKey`.

Custom model fields can't add similar logic without subclassing the
serializer, a cumbersome solution which doesn't scale well in the presence
of multiple custom fields.

My motivation for a generic hook is to add serialization support for
MongoDB's [https://django-mongodb-
backend.readthedocs.io/en/latest/ref/models/fields/#embeddedmodelfield
EmbeddedModelField], `EmbeddedModelArrayField`,
`PolymorphicEmbeddedModelField`, and `PolymorphicEmbeddedModelArrayField`.

An early prototype:
{{{#!diff
diff --git a/django/core/serializers/python.py
b/django/core/serializers/python.py
index 2929874b01..1a4f5a1336 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -39,9 +39,34 @@ class Serializer(base.Serializer):
data["fields"] = self._current
return data

+ def get_fields_from_model(self, obj, *, polymorphic=False):
+ data = {
+ field.name: self._value_from_field(obj, field)
+ for field in obj._meta.local_fields
+ }
+ if polymorphic:
+ data["_label"] = obj._meta.label
+ return data
+
def _value_from_field(self, obj, field):
if isinstance(field, CompositePrimaryKey):
return [self._value_from_field(obj, f) for f in field]
+ if hasattr(field, "embedded_model"):
+ sub_obj = getattr(obj, field.attname)
+ if sub_obj is None:
+ return None
+ if isinstance(sub_obj, list):
+ return [self.get_fields_from_model(sub) for sub in
sub_obj]
+ return self.get_fields_from_model(sub_obj)
+ if hasattr(field, "embedded_models"):
+ sub_obj = getattr(obj, field.attname)
+ if sub_obj is None:
+ return None
+ if isinstance(sub_obj, list):
+ return [
+ self.get_fields_from_model(sub, polymorphic=True) for
sub in sub_obj
+ ]
+ return self.get_fields_from_model(sub_obj, polymorphic=True)
value = field.value_from_object(obj)
# Protected types (i.e., primitives like None, numbers, dates,
# and Decimals) are passed through as is. All other values are
}}}
I don't have an immediate proposal for the API change to accomplish this.
--
Ticket URL: <https://code.djangoproject.com/ticket/36986>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 15, 2026, 1:47:16 PM (3 days ago) Mar 15
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: (none)
Type: | Status: new
Cleanup/optimization |
Component: Core | Version: dev
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Vishy Algo):

Could we do a protocol-based hook similar to this?

{{{#!diff
diff --git a/django/core/serializers/python.py
b/django/core/serializers/python.py
index 73ba24368b..b2e61d1b72 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -40,6 +40,8 @@ class Serializer(base.Serializer):
return data

def _value_from_field(self, obj, field):
+ if hasattr(field, 'get_serializer_value'):
+ return field.get_serializer_value(obj)
if isinstance(field, CompositePrimaryKey):
return [self._value_from_field(obj, f) for f in field]
value = field.value_from_object(obj)
}}}

I guess, this gives custom fields full control while keeping it generic.
--
Ticket URL: <https://code.djangoproject.com/ticket/36986#comment:1>

Django

unread,
Mar 16, 2026, 12:11:06 AM (3 days ago) Mar 16
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: (none)
Type: | Status: new
Cleanup/optimization |
Component: Core | Version: dev
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Koushik Romel):

del
--
Ticket URL: <https://code.djangoproject.com/ticket/36986#comment:2>

Django

unread,
Mar 16, 2026, 8:27:39 AM (2 days ago) Mar 16
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: (none)
Type: | Status: new
Cleanup/optimization |
Component: Core | Version: dev
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Tim Graham):

That's insufficient. Notice that both `CompositePrimaryKey` and my example
in the description require the ability to call `self._value_from_field`
recursively. I'm considering the possibility of a registry that would
allow registering a field's function with the serializer, similar to how
lookups are registered to model fields.

Django

unread,
Mar 16, 2026, 9:15:10 AM (2 days ago) Mar 16
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: Vishy
Type: | Algo
Cleanup/optimization | Status: assigned
Component: Core | Version: dev
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Vishy Algo):

* owner: (none) => Vishy Algo
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36986#comment:3>

Django

unread,
Mar 17, 2026, 5:34:27 PM (23 hours ago) Mar 17
to django-...@googlegroups.com
#36986: Add a hook to Serializer._value_from_field() for complex fields like
CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: Vishy
Type: | Algo
Cleanup/optimization | Status: assigned
Component: Core | Version: dev
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* stage: Unreviewed => Accepted

Comment:

Thanks, Tim. Would your field be able to implement `__iter__()`, like
`CompositePrimaryKey` does?
--
Ticket URL: <https://code.djangoproject.com/ticket/36986#comment:4>
Reply all
Reply to author
Forward
0 new messages