Ticket #10295: python.py

File python.py, 3.8 KB (added by kausikram, 6 years ago)

python.py file of serializer module

Line 
1"""
2A Python "serializer". Doesn't do much serializing per se -- just converts to
3and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for
4other serializers.
5"""
6
7from django.conf import settings
8from django.core.serializers import base
9from django.db import models
10from django.utils.encoding import smart_unicode
11
12class Serializer(base.Serializer):
13    """
14    Serializes a QuerySet to basic Python objects.
15    """
16
17    internal_use_only = True
18
19    def start_serialization(self):
20        self._current = None
21        self.objects = []
22
23    def end_serialization(self):
24        pass
25
26    def start_object(self, obj):
27        self._current = {}
28
29    def end_object(self, obj):
30        self.objects.append({
31            "model"  : smart_unicode(obj._meta),
32            "pk"     : smart_unicode(obj._get_pk_val(), strings_only=True),
33            "name"   : smart_unicode(obj._meta.pk.name),
34            "fields" : self._current
35        })
36        self._current = None
37
38    def handle_field(self, obj, field):
39        self._current[field.name] = smart_unicode(getattr(obj, field.name), strings_only=True)
40
41    def handle_fk_field(self, obj, field):
42        related = getattr(obj, field.name)
43        if related is not None:
44            if field.rel.field_name == related._meta.pk.name:
45                # Related to remote object via primary key
46                related = related._get_pk_val()
47            else:
48                # Related to remote object via other field
49                related = getattr(related, field.rel.field_name)
50        self._current[field.name] = smart_unicode(related, strings_only=True)
51
52    def handle_m2m_field(self, obj, field):
53        if field.creates_table:
54            self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True)
55                               for related in getattr(obj, field.name).iterator()]
56
57    def getvalue(self):
58        return self.objects
59
60def Deserializer(object_list, **options):
61    """
62    Deserialize simple Python objects back into Django ORM instances.
63
64    It's expected that you pass the Python objects themselves (instead of a
65    stream or a string) to the constructor
66    """
67    models.get_apps()
68    for d in object_list:
69        # Look up the model and starting build a dict of data for it.
70        Model = _get_model(d["model"])
71        data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
72        m2m_data = {}
73
74        # Handle each field
75        for (field_name, field_value) in d["fields"].iteritems():
76            if isinstance(field_value, str):
77                field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
78
79            field = Model._meta.get_field(field_name)
80
81            # Handle M2M relations
82            if field.rel and isinstance(field.rel, models.ManyToManyRel):
83                m2m_convert = field.rel.to._meta.pk.to_python
84                m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value]
85
86            # Handle FK fields
87            elif field.rel and isinstance(field.rel, models.ManyToOneRel):
88                if field_value is not None:
89                    data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
90                else:
91                    data[field.attname] = None
92
93            # Handle all other fields
94            else:
95                data[field.name] = field.to_python(field_value)
96
97        yield base.DeserializedObject(Model(**data), m2m_data)
98
99def _get_model(model_identifier):
100    """
101    Helper to look up a model from an "app_label.module_name" string.
102    """
103    try:
104        Model = models.get_model(*model_identifier.split("."))
105    except TypeError:
106        Model = None
107    if Model is None:
108        raise base.DeserializationError(u"Invalid model identifier: '%s'" % model_identifier)
109    return Model
Back to Top