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

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.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 

11 

12 

13class Serializer(base.Serializer): 

14 """ 

15 Serialize a QuerySet to basic Python objects. 

16 """ 

17 

18 internal_use_only = True 

19 

20 def start_serialization(self): 

21 self._current = None 

22 self.objects = [] 

23 

24 def end_serialization(self): 

25 pass 

26 

27 def start_object(self, obj): 

28 self._current = {} 

29 

30 def end_object(self, obj): 

31 self.objects.append(self.get_dump_object(obj)) 

32 self._current = None 

33 

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 

40 

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) 

47 

48 def handle_field(self, obj, field): 

49 self._current[field.name] = self._value_from_field(obj, field) 

50 

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 

63 

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 ): 

69 

70 def m2m_value(value): 

71 return value.natural_key() 

72 

73 else: 

74 

75 def m2m_value(value): 

76 return self._value_from_field(value, value._meta.pk) 

77 

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] 

83 

84 def getvalue(self): 

85 return self.objects 

86 

87 

88def Deserializer( 

89 object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options 

90): 

91 """ 

92 Deserialize simple Python objects back into Django ORM instances. 

93 

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> 

99 

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 = {} 

119 

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] 

123 

124 # Handle each field 

125 for (field_name, field_value) in d["fields"].items(): 

126 

127 if ignorenonexistent and field_name not in field_names: 

128 # skip fields no longer on model 

129 continue 

130 

131 field = Model._meta.get_field(field_name) 

132 

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 ) 

173 

174 obj = base.build_instance(Model, data, using) 

175 yield base.DeserializedObject(obj, m2m_data, deferred_fields) 

176 

177 

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 )