diff options
| author | Amir Karimi <amk9978@gmail.com> | 2024-09-12 10:56:18 +0200 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-09-17 11:00:49 +0200 |
| commit | ee5147cfd7de2add74a285537a8968ec074e70cd (patch) | |
| tree | 64129a4de2722fb78dc486c83656f9d907aab296 /docs/topics/serialization.txt | |
| parent | a060a22ee2dde7aa29a5a29120087c4864887325 (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.txt | 80 |
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 |
