Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/core/serializers/python.py: 15%
98 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
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"""
7from django.apps import apps
8from django.core.serializers import base
9from django.db import DEFAULT_DB_ALIAS, models
10from django.utils.encoding import is_protected_type
13class Serializer(base.Serializer):
14 """
15 Serialize a QuerySet to basic Python objects.
16 """
18 internal_use_only = True
20 def start_serialization(self):
21 self._current = None
22 self.objects = []
24 def end_serialization(self):
25 pass
27 def start_object(self, obj):
28 self._current = {}
30 def end_object(self, obj):
31 self.objects.append(self.get_dump_object(obj))
32 self._current = None
34 def get_dump_object(self, obj):
35 data = {"model": str(obj._meta)}
36 if not self.use_natural_primary_keys or not hasattr(obj, "natural_key"):
37 data["pk"] = self._value_from_field(obj, obj._meta.pk)
38 data["fields"] = self._current
39 return data
41 def _value_from_field(self, obj, field):
42 value = field.value_from_object(obj)
43 # Protected types (i.e., primitives like None, numbers, dates,
44 # and Decimals) are passed through as is. All other values are
45 # converted to string first.
46 return value if is_protected_type(value) else field.value_to_string(obj)
48 def handle_field(self, obj, field):
49 self._current[field.name] = self._value_from_field(obj, field)
51 def handle_fk_field(self, obj, field):
52 if self.use_natural_foreign_keys and hasattr(
53 field.remote_field.model, "natural_key"
54 ):
55 related = getattr(obj, field.name)
56 if related:
57 value = related.natural_key()
58 else:
59 value = None
60 else:
61 value = self._value_from_field(obj, field)
62 self._current[field.name] = value
64 def handle_m2m_field(self, obj, field):
65 if field.remote_field.through._meta.auto_created:
66 if self.use_natural_foreign_keys and hasattr(
67 field.remote_field.model, "natural_key"
68 ):
70 def m2m_value(value):
71 return value.natural_key()
73 else:
75 def m2m_value(value):
76 return self._value_from_field(value, value._meta.pk)
78 m2m_iter = getattr(obj, "_prefetched_objects_cache", {}).get(
79 field.name,
80 getattr(obj, field.name).iterator(),
81 )
82 self._current[field.name] = [m2m_value(related) for related in m2m_iter]
84 def getvalue(self):
85 return self.objects
88def Deserializer(
89 object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options
90):
91 """
92 Deserialize simple Python objects back into Django ORM instances.
94 It's expected that you pass the Python objects themselves (instead of a
95 stream or a string) to the constructor
96 """
97 handle_forward_references = options.pop("handle_forward_references", False)
98 field_names_cache = {} # Model: <list of field_names>
100 for d in object_list:
101 # Look up the model and starting build a dict of data for it.
102 try:
103 Model = _get_model(d["model"])
104 except base.DeserializationError:
105 if ignorenonexistent:
106 continue
107 else:
108 raise
109 data = {}
110 if "pk" in d:
111 try:
112 data[Model._meta.pk.attname] = Model._meta.pk.to_python(d.get("pk"))
113 except Exception as e:
114 raise base.DeserializationError.WithData(
115 e, d["model"], d.get("pk"), None
116 )
117 m2m_data = {}
118 deferred_fields = {}
120 if Model not in field_names_cache:
121 field_names_cache[Model] = {f.name for f in Model._meta.get_fields()}
122 field_names = field_names_cache[Model]
124 # Handle each field
125 for (field_name, field_value) in d["fields"].items():
127 if ignorenonexistent and field_name not in field_names:
128 # skip fields no longer on model
129 continue
131 field = Model._meta.get_field(field_name)
133 # Handle M2M relations
134 if field.remote_field and isinstance(
135 field.remote_field, models.ManyToManyRel
136 ):
137 try:
138 values = base.deserialize_m2m_values(
139 field, field_value, using, handle_forward_references
140 )
141 except base.M2MDeserializationError as e:
142 raise base.DeserializationError.WithData(
143 e.original_exc, d["model"], d.get("pk"), e.pk
144 )
145 if values == base.DEFER_FIELD:
146 deferred_fields[field] = field_value
147 else:
148 m2m_data[field.name] = values
149 # Handle FK fields
150 elif field.remote_field and isinstance(
151 field.remote_field, models.ManyToOneRel
152 ):
153 try:
154 value = base.deserialize_fk_value(
155 field, field_value, using, handle_forward_references
156 )
157 except Exception as e:
158 raise base.DeserializationError.WithData(
159 e, d["model"], d.get("pk"), field_value
160 )
161 if value == base.DEFER_FIELD:
162 deferred_fields[field] = field_value
163 else:
164 data[field.attname] = value
165 # Handle all other fields
166 else:
167 try:
168 data[field.name] = field.to_python(field_value)
169 except Exception as e:
170 raise base.DeserializationError.WithData(
171 e, d["model"], d.get("pk"), field_value
172 )
174 obj = base.build_instance(Model, data, using)
175 yield base.DeserializedObject(obj, m2m_data, deferred_fields)
178def _get_model(model_identifier):
179 """Look up a model from an "app_label.model_name" string."""
180 try:
181 return apps.get_model(model_identifier)
182 except (LookupError, TypeError):
183 raise base.DeserializationError(
184 "Invalid model identifier: '%s'" % model_identifier
185 )