summaryrefslogtreecommitdiff
path: root/docs/topics/serialization.txt
diff options
context:
space:
mode:
authorAmir Karimi <amk9978@gmail.com>2024-09-12 10:56:18 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-09-17 11:00:49 +0200
commitee5147cfd7de2add74a285537a8968ec074e70cd (patch)
tree64129a4de2722fb78dc486c83656f9d907aab296 /docs/topics/serialization.txt
parenta060a22ee2dde7aa29a5a29120087c4864887325 (diff)
Fixed #29522 -- Refactored the Deserializer functions to classes.
Co-authored-by: Emad Mokhtar <emad.mokhtar@veneficus.nl>
Diffstat (limited to 'docs/topics/serialization.txt')
-rw-r--r--docs/topics/serialization.txt80
1 files changed, 80 insertions, 0 deletions
diff --git a/docs/topics/serialization.txt b/docs/topics/serialization.txt
index 0bb57642ab..12cc616a21 100644
--- a/docs/topics/serialization.txt
+++ b/docs/topics/serialization.txt
@@ -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