2 A Python "serializer". Doesn't do much serializing per se -- just converts to
3 and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for
7 from django
.conf
import settings
8 from django
.core
.serializers
import base
9 from django
.db
import models
10 from django
.utils
.encoding
import smart_unicode
12 class Serializer(base
.Serializer
):
14 Serializes a QuerySet to basic Python objects.
17 internal_use_only
= True
19 def start_serialization(self
):
23 def end_serialization(self
):
26 def start_object(self
, obj
):
29 def end_object(self
, obj
):
31 "model" : smart_unicode(obj
._meta
),
32 "pk" : smart_unicode(obj
._get
_pk
_val
(), strings_only
=True),
33 "fields" : self
._current
37 def handle_field(self
, obj
, field
):
38 self
._current
[field
.name
] = smart_unicode(getattr(obj
, field
.name
), strings_only
=True)
40 def handle_fk_field(self
, obj
, field
):
41 related
= getattr(obj
, field
.name
)
42 if related
is not None:
43 if field
.rel
.field_name
== related
._meta
.pk
.name
:
44 # Related to remote object via primary key
45 related
= related
._get
_pk
_val
()
47 # Related to remote object via other field
48 related
= getattr(related
, field
.rel
.field_name
)
49 self
._current
[field
.name
] = smart_unicode(related
, strings_only
=True)
51 def handle_m2m_field(self
, obj
, field
):
52 self
._current
[field
.name
] = [smart_unicode(related
._get
_pk
_val
(), strings_only
=True)
53 for related
in getattr(obj
, field
.name
).iterator()]
58 def Deserializer(object_list
, **options
):
60 Deserialize simple Python objects back into Django ORM instances.
62 It's expected that you pass the Python objects themselves (instead of a
63 stream or a string) to the constructor
67 # Look up the model and starting build a dict of data for it.
68 Model
= _get_model(d
["model"])
69 data
= {Model
._meta
.pk
.attname
: Model
._meta
.pk
.to_python(d
["pk"])}
73 for (field_name
, field_value
) in d
["fields"].iteritems():
74 if isinstance(field_value
, str):
75 field_value
= smart_unicode(field_value
, options
.get("encoding", settings
.DEFAULT_CHARSET
), strings_only
=True)
77 field
= Model
._meta
.get_field(field_name
)
79 # Handle M2M relations
80 if field
.rel
and isinstance(field
.rel
, models
.ManyToManyRel
):
81 m2m_convert
= field
.rel
.to
._meta
.pk
.to_python
82 m2m_data
[field
.name
] = [m2m_convert(smart_unicode(pk
)) for pk
in field_value
]
85 elif field
.rel
and isinstance(field
.rel
, models
.ManyToOneRel
):
87 data
[field
.attname
] = field
.rel
.to
._meta
.get_field(field
.rel
.field_name
).to_python(field_value
)
89 data
[field
.attname
] = None
91 # Handle all other fields
93 data
[field
.name
] = field
.to_python(field_value
)
95 yield base
.DeserializedObject(Model(**data
), m2m_data
)
97 def _get_model(model_identifier
):
99 Helper to look up a model from an "app_label.module_name" string.
102 Model
= models
.get_model(*model_identifier
.split("."))
106 raise base
.DeserializationError(u
"Invalid model identifier: '%s'" % model_identifier
)