Десериализация модели Джанго с пустым ПК - PullRequest
8 голосов
/ 16 июля 2009

Я сериализовал мою модель Django:

serializers.serialize(MyModel.objects.filter(color="Red"))

и получил этот вывод:

<object model="example.example" pk="133">
    <field name="name" type="CharField">John Smith</field>
    <field name="color" type="CharField">Red</field>
    ... #more fields
</object>

Итак, вы можете видеть, что у меня есть pk = "133":

И теперь я хочу снова десериализовать это в модель django и сохранить () в базу данных, но с другим pk, поэтому он должен создать новую запись с новым id.

Я пытаюсь разобрать XML и изменить pk, используя:

  • pk = "" - парсер жалуется, что pk должно быть целым числом
  • pk = "- 1" или "0" - фактически создает запись с id / pk = "1" или "0"
  • pk = "None" или None или "null" - синтаксический анализатор жалуется, что pk должно быть целым числом
  • удалить атрибут "pk" - парсер жалуется, что атрибут является обязательным

В статье Django Serialization приведен пример десериализации из JSON с нулевым "pk".

# You can easily create new objects by deserializing data with an empty PK
# (It's easier to demo this with JSON...)
>>> new_author_json = '[{"pk": null, "model": "serializers.author", "fields": {"name": "Bill"}}]'
>>> for obj in serializers.deserialize("json", new_author_json):
...     obj.save()

(на самом деле это для 0,96, но я предполагаю, что это должно работать для 1 *. Также)

Так что в JSON pk может иметь значение null, но в XML он жалуется. Как установить pk в ноль для XML?

Спасибо

1 Ответ

5 голосов
/ 16 июля 2009

Похоже, ошибка в Django. Невозможно предоставить пустое (или пустое / пустое) «pk» для сериализованного объекта XML.

Из django / core / serializers / xml_serializer.py:

class Deserializer(base.Deserializer):
    ...
    def _handle_object(self, node):
    ...
        pk = node.getAttribute("pk")
        if not pk:
            raise base.DeserializationError("<object> node is missing the 'pk' attribute")

        data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
    ...

Если атрибут pk отсутствует - возникает исключение. Поэтому мы должны предоставить некоторые ПК.

Из django / models / fields / init .py

class AutoField(Field):
    ...
    def to_python(self, value):
        if value is None:
            return value
        try:
            return int(value)
        except (TypeError, ValueError):
            raise exceptions.ValidationError(
                _("This value must be an integer."))
    ...

Если pk не является целым числом - также исключение.

Похоже, нет способа предоставить пустой ПК.

Обходной путь может быть:

  1. получить максимальный идентификатор от MyModel
  2. id + = 1
  3. установить "pk" в моем xml с новым идентификатором
  4. десериализовать в модель
  5. сохранить ()

Это немного сложно, потому что во время шагов 1-5 таблица должна быть заблокирована ... каким-то образом ... просто, чтобы избежать конфликта ID.

EDIT:

Обходной путь:

  1. Set pk = "999999" (некоторое временное целое значение)
  2. Во время итерации установите id и pk на None, а затем сохраните ()

    mymodels_iterator = serializers.deserialize ("xml", fixed_pk_serialized_xml_model)

    для mymodel в mymodels_iterator:

    mymodel.object.id = None
    mymodel.object.pk = None
    mymodel.save()
    

И это работает!

Благодаря комментарию Евгения о методе clone ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...