mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #29522 -- Refactored the Deserializer functions to classes.
Co-authored-by: Emad Mokhtar <emad.mokhtar@veneficus.nl>
This commit is contained in:
@@ -347,6 +347,86 @@ again a mapping with the key being name of the field and the value the value:
|
||||
|
||||
Referential fields are again represented by the PK or sequence of PKs.
|
||||
|
||||
.. _custom-serialization-formats:
|
||||
|
||||
Custom serialization formats
|
||||
----------------------------
|
||||
|
||||
In addition to the default formats, you can create a custom serialization
|
||||
format.
|
||||
|
||||
For example, let’s consider a csv serializer and deserializer. First, define a
|
||||
``Serializer`` and a ``Deserializer`` class. These can override existing
|
||||
serialization format classes:
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``path/to/custom_csv_serializer.py``
|
||||
|
||||
import csv
|
||||
|
||||
from django.apps import apps
|
||||
from django.core import serializers
|
||||
from django.core.serializers.base import DeserializationError
|
||||
|
||||
|
||||
class Serializer(serializers.python.Serializer):
|
||||
def get_dump_object(self, obj):
|
||||
dumped_object = super().get_dump_object(obj)
|
||||
row = [dumped_object["model"], str(dumped_object["pk"])]
|
||||
row += [str(value) for value in dumped_object["fields"].values()]
|
||||
return ",".join(row), dumped_object["model"]
|
||||
|
||||
def end_object(self, obj):
|
||||
dumped_object_str, model = self.get_dump_object(obj)
|
||||
if self.first:
|
||||
fields = [field.name for field in apps.get_model(model)._meta.fields]
|
||||
header = ",".join(fields)
|
||||
self.stream.write(f"model,{header}\n")
|
||||
self.stream.write(f"{dumped_object_str}\n")
|
||||
|
||||
def getvalue(self):
|
||||
return super(serializers.python.Serializer, self).getvalue()
|
||||
|
||||
|
||||
class Deserializer(serializers.python.Deserializer):
|
||||
def __init__(self, stream_or_string, **options):
|
||||
if isinstance(stream_or_string, bytes):
|
||||
stream_or_string = stream_or_string.decode()
|
||||
if isinstance(stream_or_string, str):
|
||||
stream_or_string = stream_or_string.splitlines()
|
||||
try:
|
||||
objects = csv.DictReader(stream_or_string)
|
||||
except Exception as exc:
|
||||
raise DeserializationError() from exc
|
||||
super().__init__(objects, **options)
|
||||
|
||||
def _handle_object(self, obj):
|
||||
try:
|
||||
model_fields = apps.get_model(obj["model"])._meta.fields
|
||||
obj["fields"] = {
|
||||
field.name: obj[field.name]
|
||||
for field in model_fields
|
||||
if field.name in obj
|
||||
}
|
||||
yield from super()._handle_object(obj)
|
||||
except (GeneratorExit, DeserializationError):
|
||||
raise
|
||||
except Exception as exc:
|
||||
raise DeserializationError(f"Error deserializing object: {exc}") from exc
|
||||
|
||||
Then add the module containing the serializer definitions to your
|
||||
:setting:`SERIALIZATION_MODULES` setting::
|
||||
|
||||
SERIALIZATION_MODULES = {
|
||||
"csv": "path.to.custom_csv_serializer",
|
||||
"json": "django.core.serializers.json",
|
||||
}
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
A ``Deserializer`` class definition was added to each of the provided
|
||||
serialization formats.
|
||||
|
||||
.. _topics-serialization-natural-keys:
|
||||
|
||||
Natural keys
|
||||
|
||||
Reference in New Issue
Block a user