def build_data(self, model, field_names, pk, data, using=None): m2m = {} if pk is not None: try: yield (model._meta.pk.attname, model._meta.pk.to_python(pk)) except Exception as err: raise base.DeserializationError.WithData(err, m_name, pk, None) for (field_name, field_value) in data.items(): if field_name not in field_names: continue field = model._meta.get_field(field_name) if field.remote_field and isinstance(field.remote_field, models.ManyToManyRel): values = base.deserialize_m2m_values(field, field_value, using, False) m2m[field.name] = values # Handle FK fields elif field.remote_field and isinstance(field.remote_field, models.ManyToOneRel): value = base.deserialize_fk_value(field, field_value, using, False) yield (field.attname, value) else: # Everything else yield (field.name, field.to_python(field_value)) # Not great yield ('m2m', m2m)
def _build_model_data(model, obj_pk, fields_data, using): data = {} # Handle each field for (field_name, field_value) in fields_data.items(): field = model._meta.get_field(field_name) # Handle many-to-many relations if field.many_to_many: raise NotImplementedError('Many-to-many fields not supported') # Handle one-to-many relations if field.one_to_many: raise NotImplementedError('One-to-many fields not supported') # Handle fk fields if field.many_to_one: try: value = base.deserialize_fk_value(field, field_value, using, False) except Exception as exc: raise base.DeserializationError.WithData( exc, model._meta.model_name, obj_pk, field_value, ) from exc data[field.attname] = value # Handle all other fields else: try: data[field.name] = field.to_python(field_value) except Exception as exc: raise base.DeserializationError.WithData( exc, model._meta.model_name, obj_pk, field_value, ) from exc return data
def Deserializer(object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options): """ Deserialize simple Python objects back into Django ORM instances. It's expected that you pass the Python objects themselves (instead of a stream or a string) to the constructor """ handle_forward_references = options.pop("handle_forward_references", False) field_names_cache = {} # Model: <list of field_names> for d in object_list: # Look up the model and starting build a dict of data for it. try: Model = _get_model(d["model"]) except base.DeserializationError: if ignorenonexistent: continue else: raise data = {} if "pk" in d: try: data[Model._meta.pk.attname] = Model._meta.pk.to_python( d.get("pk")) except Exception as e: raise base.DeserializationError.WithData( e, d["model"], d.get("pk"), None) m2m_data = {} deferred_fields = {} if Model not in field_names_cache: field_names_cache[Model] = { f.name for f in Model._meta.get_fields() } field_names = field_names_cache[Model] # Handle each field for (field_name, field_value) in d["fields"].items(): if ignorenonexistent and field_name not in field_names: # skip fields no longer on model continue field = Model._meta.get_field(field_name) # Handle M2M relations if field.remote_field and isinstance(field.remote_field, models.ManyToManyRel): try: values = base.deserialize_m2m_values( field, field_value, using, handle_forward_references) except base.M2MDeserializationError as e: raise base.DeserializationError.WithData( e.original_exc, d["model"], d.get("pk"), e.pk) if values == base.DEFER_FIELD: deferred_fields[field] = field_value else: m2m_data[field.name] = values # Handle FK fields elif field.remote_field and isinstance(field.remote_field, models.ManyToOneRel): try: value = base.deserialize_fk_value( field, field_value, using, handle_forward_references) except Exception as e: raise base.DeserializationError.WithData( e, d["model"], d.get("pk"), field_value) if value == base.DEFER_FIELD: deferred_fields[field] = field_value else: data[field.attname] = value # Handle all other fields else: try: data[field.name] = field.to_python(field_value) except Exception as e: raise base.DeserializationError.WithData( e, d["model"], d.get("pk"), field_value) obj = base.build_instance(Model, data, using) yield base.DeserializedObject(obj, m2m_data, deferred_fields)
def Deserializer(object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options): """ Deserialize simple Python objects back into Django ORM instances. It's expected that you pass the Python objects themselves (instead of a stream or a string) to the constructor """ field_names_cache = {} # Model: <list of field_names> for d in object_list: # Look up the model and starting build a dict of data for it. try: Model = _get_model(d["model"]) except base.DeserializationError: if ignorenonexistent: continue else: raise data = {} if 'pk' in d: try: data[Model._meta.pk.attname] = Model._meta.pk.to_python(d.get('pk')) except Exception as e: raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), None) m2m_data = {} if Model not in field_names_cache: field_names_cache[Model] = {f.name for f in Model._meta.get_fields()} field_names = field_names_cache[Model] # Handle each field for (field_name, field_value) in d["fields"].items(): if ignorenonexistent and field_name not in field_names: # skip fields no longer on model continue field = Model._meta.get_field(field_name) # Handle M2M relations if field.remote_field and isinstance(field.remote_field, models.ManyToManyRel): try: values = base.deserialize_m2m_values(field, field_value, using) except base.M2MDeserializationError as e: raise base.DeserializationError.WithData(e.original_exc, d['model'], d.get('pk'), e.pk) m2m_data[field.name] = values # Handle FK fields elif field.remote_field and isinstance(field.remote_field, models.ManyToOneRel): try: value = base.deserialize_fk_value(field, field_value, using) except Exception as e: raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value) data[field.attname] = value # Handle all other fields else: try: data[field.name] = field.to_python(field_value) except Exception as e: raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value) obj = base.build_instance(Model, data, using) yield base.DeserializedObject(obj, m2m_data)