I've serialized my django model:
serializers.serialize(MyModel.objects.filter(color="Red"))
and got this output:
<object model="example.example" pk="133">
<field name="name" type="CharField">John Smith</field>
<field name="color" type="CharField">Red</field>
... #more fields
</object>
So you can see I have pk="133":
And now I want to deserialize this into django model again and save() into database but with different pk so it should create new record with new id.
I'm trying to parse XML and change pk using:
In Django Serialization article there is an example how to deserialize from JSON with null "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()
(It's actually for 0.96, but I'm assuming it should work for 1.* also)
So in JSON pk can be null but in XML it complains. How to set pk to null for XML?
Thanks
Looks like bug in Django. There are no way to provide empty (or null/None) "pk" for XML serialized object.
From 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)}
...
If pk attribute is missing - exception is raised. So we have to provide some pk.
From 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."))
...
If pk is not integer - also exception.
It looks like there are no way to provide empty pk.
Workaround could be:
It's little bit tricky because during steps 1-5 table should be locked.. somehow.. just to avoid id collision.
EDIT:
Workaround is:
During iteration set id and pk to None and later save()
mymodels_iterator = serializers.deserialize("xml", fixed_pk_serialized_xml_model)
for mymodel in mymodels_iterator:
mymodel.object.id = None
mymodel.object.pk = None
mymodel.save()
And it works!
Thanks to Evgeny's comment about clone() method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With