4 other serializers. |
4 other serializers. |
5 """ |
5 """ |
6 |
6 |
7 from django.conf import settings |
7 from django.conf import settings |
8 from django.core.serializers import base |
8 from django.core.serializers import base |
9 from django.db import models |
9 from django.db import models, DEFAULT_DB_ALIAS |
10 from django.utils.encoding import smart_unicode, is_protected_type |
10 from django.utils.encoding import smart_unicode, is_protected_type |
11 |
11 |
12 class Serializer(base.Serializer): |
12 class Serializer(base.Serializer): |
13 """ |
13 """ |
14 Serializes a QuerySet to basic Python objects. |
14 Serializes a QuerySet to basic Python objects. |
45 self._current[field.name] = field.value_to_string(obj) |
45 self._current[field.name] = field.value_to_string(obj) |
46 |
46 |
47 def handle_fk_field(self, obj, field): |
47 def handle_fk_field(self, obj, field): |
48 related = getattr(obj, field.name) |
48 related = getattr(obj, field.name) |
49 if related is not None: |
49 if related is not None: |
50 if field.rel.field_name == related._meta.pk.name: |
50 if self.use_natural_keys and hasattr(related, 'natural_key'): |
51 # Related to remote object via primary key |
51 related = related.natural_key() |
52 related = related._get_pk_val() |
|
53 else: |
52 else: |
54 # Related to remote object via other field |
53 if field.rel.field_name == related._meta.pk.name: |
55 related = getattr(related, field.rel.field_name) |
54 # Related to remote object via primary key |
56 self._current[field.name] = smart_unicode(related, strings_only=True) |
55 related = related._get_pk_val() |
|
56 else: |
|
57 # Related to remote object via other field |
|
58 related = smart_unicode(getattr(related, field.rel.field_name), strings_only=True) |
|
59 self._current[field.name] = related |
57 |
60 |
58 def handle_m2m_field(self, obj, field): |
61 def handle_m2m_field(self, obj, field): |
59 if field.creates_table: |
62 if field.rel.through._meta.auto_created: |
60 self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True) |
63 if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'): |
|
64 m2m_value = lambda value: value.natural_key() |
|
65 else: |
|
66 m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True) |
|
67 self._current[field.name] = [m2m_value(related) |
61 for related in getattr(obj, field.name).iterator()] |
68 for related in getattr(obj, field.name).iterator()] |
62 |
69 |
63 def getvalue(self): |
70 def getvalue(self): |
64 return self.objects |
71 return self.objects |
65 |
72 |
68 Deserialize simple Python objects back into Django ORM instances. |
75 Deserialize simple Python objects back into Django ORM instances. |
69 |
76 |
70 It's expected that you pass the Python objects themselves (instead of a |
77 It's expected that you pass the Python objects themselves (instead of a |
71 stream or a string) to the constructor |
78 stream or a string) to the constructor |
72 """ |
79 """ |
|
80 db = options.pop('using', DEFAULT_DB_ALIAS) |
73 models.get_apps() |
81 models.get_apps() |
74 for d in object_list: |
82 for d in object_list: |
75 # Look up the model and starting build a dict of data for it. |
83 # Look up the model and starting build a dict of data for it. |
76 Model = _get_model(d["model"]) |
84 Model = _get_model(d["model"]) |
77 data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} |
85 data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} |
84 |
92 |
85 field = Model._meta.get_field(field_name) |
93 field = Model._meta.get_field(field_name) |
86 |
94 |
87 # Handle M2M relations |
95 # Handle M2M relations |
88 if field.rel and isinstance(field.rel, models.ManyToManyRel): |
96 if field.rel and isinstance(field.rel, models.ManyToManyRel): |
89 m2m_convert = field.rel.to._meta.pk.to_python |
97 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): |
90 m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value] |
98 def m2m_convert(value): |
|
99 if hasattr(value, '__iter__'): |
|
100 return field.rel.to._default_manager.db_manager(db).get_by_natural_key(*value).pk |
|
101 else: |
|
102 return smart_unicode(field.rel.to._meta.pk.to_python(value)) |
|
103 else: |
|
104 m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v)) |
|
105 m2m_data[field.name] = [m2m_convert(pk) for pk in field_value] |
91 |
106 |
92 # Handle FK fields |
107 # Handle FK fields |
93 elif field.rel and isinstance(field.rel, models.ManyToOneRel): |
108 elif field.rel and isinstance(field.rel, models.ManyToOneRel): |
94 if field_value is not None: |
109 if field_value is not None: |
95 data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) |
110 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): |
|
111 if hasattr(field_value, '__iter__'): |
|
112 obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value) |
|
113 value = getattr(obj, field.rel.field_name) |
|
114 # If this is a natural foreign key to an object that |
|
115 # has a FK/O2O as the foreign key, use the FK value |
|
116 if field.rel.to._meta.pk.rel: |
|
117 value = value.pk |
|
118 else: |
|
119 value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) |
|
120 data[field.attname] = value |
|
121 else: |
|
122 data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) |
96 else: |
123 else: |
97 data[field.attname] = None |
124 data[field.attname] = None |
98 |
125 |
99 # Handle all other fields |
126 # Handle all other fields |
100 else: |
127 else: |