Beispiel #1
0
    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)
Beispiel #2
0
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)