root / env / lib / python2.7 / site-packages / django / core / serializers / python.py @ 1a305335
History | View | Annotate | Download (5.51 KB)
1 | 1a305335 | officers | """
|
---|---|---|---|
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
|
||
4 | other serializers.
|
||
5 | """
|
||
6 | |||
7 | from django.conf import settings |
||
8 | from django.core.serializers import base |
||
9 | from django.db import models, DEFAULT_DB_ALIAS |
||
10 | from django.utils.encoding import smart_unicode, is_protected_type |
||
11 | |||
12 | class 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 | "fields" : self._current |
||
34 | }) |
||
35 | self._current = None |
||
36 | |||
37 | def handle_field(self, obj, field): |
||
38 | value = field._get_val_from_obj(obj) |
||
39 | # Protected types (i.e., primitives like None, numbers, dates,
|
||
40 | # and Decimals) are passed through as is. All other values are
|
||
41 | # converted to string first.
|
||
42 | if is_protected_type(value):
|
||
43 | self._current[field.name] = value
|
||
44 | else:
|
||
45 | self._current[field.name] = field.value_to_string(obj)
|
||
46 | |||
47 | def handle_fk_field(self, obj, field): |
||
48 | if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'): |
||
49 | related = getattr(obj, field.name)
|
||
50 | if related:
|
||
51 | value = related.natural_key() |
||
52 | else:
|
||
53 | value = None
|
||
54 | else:
|
||
55 | value = getattr(obj, field.get_attname())
|
||
56 | self._current[field.name] = value
|
||
57 | |||
58 | def handle_m2m_field(self, obj, field): |
||
59 | if field.rel.through._meta.auto_created:
|
||
60 | if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'): |
||
61 | m2m_value = lambda value: value.natural_key()
|
||
62 | else:
|
||
63 | m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True) |
||
64 | self._current[field.name] = [m2m_value(related)
|
||
65 | for related in getattr(obj, field.name).iterator()] |
||
66 | |||
67 | def getvalue(self): |
||
68 | return self.objects |
||
69 | |||
70 | def Deserializer(object_list, **options): |
||
71 | """
|
||
72 | Deserialize simple Python objects back into Django ORM instances.
|
||
73 |
|
||
74 | It's expected that you pass the Python objects themselves (instead of a
|
||
75 | stream or a string) to the constructor
|
||
76 | """
|
||
77 | db = options.pop('using', DEFAULT_DB_ALIAS)
|
||
78 | models.get_apps() |
||
79 | for d in object_list: |
||
80 | # Look up the model and starting build a dict of data for it.
|
||
81 | Model = _get_model(d["model"])
|
||
82 | data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
|
||
83 | m2m_data = {} |
||
84 | |||
85 | # Handle each field
|
||
86 | for (field_name, field_value) in d["fields"].iteritems(): |
||
87 | if isinstance(field_value, str): |
||
88 | field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True) |
||
89 | |||
90 | field = Model._meta.get_field(field_name) |
||
91 | |||
92 | # Handle M2M relations
|
||
93 | if field.rel and isinstance(field.rel, models.ManyToManyRel): |
||
94 | if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): |
||
95 | def m2m_convert(value): |
||
96 | if hasattr(value, '__iter__'): |
||
97 | return field.rel.to._default_manager.db_manager(db).get_by_natural_key(*value).pk
|
||
98 | else:
|
||
99 | return smart_unicode(field.rel.to._meta.pk.to_python(value))
|
||
100 | else:
|
||
101 | m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v))
|
||
102 | m2m_data[field.name] = [m2m_convert(pk) for pk in field_value] |
||
103 | |||
104 | # Handle FK fields
|
||
105 | elif field.rel and isinstance(field.rel, models.ManyToOneRel): |
||
106 | if field_value is not None: |
||
107 | if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): |
||
108 | if hasattr(field_value, '__iter__'): |
||
109 | obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value) |
||
110 | value = getattr(obj, field.rel.field_name)
|
||
111 | # If this is a natural foreign key to an object that
|
||
112 | # has a FK/O2O as the foreign key, use the FK value
|
||
113 | if field.rel.to._meta.pk.rel:
|
||
114 | value = value.pk |
||
115 | else:
|
||
116 | value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) |
||
117 | data[field.attname] = value |
||
118 | else:
|
||
119 | data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) |
||
120 | else:
|
||
121 | data[field.attname] = None
|
||
122 | |||
123 | # Handle all other fields
|
||
124 | else:
|
||
125 | data[field.name] = field.to_python(field_value) |
||
126 | |||
127 | yield base.DeserializedObject(Model(**data), m2m_data)
|
||
128 | |||
129 | def _get_model(model_identifier): |
||
130 | """
|
||
131 | Helper to look up a model from an "app_label.module_name" string.
|
||
132 | """
|
||
133 | try:
|
||
134 | Model = models.get_model(*model_identifier.split("."))
|
||
135 | except TypeError: |
||
136 | Model = None
|
||
137 | if Model is None: |
||
138 | raise base.DeserializationError(u"Invalid model identifier: '%s'" % model_identifier) |
||
139 | return Model |