Django and OneToOneField Tools

As stated here , objects are created automatically for models with the OneToOne relationship to other models. Therefore, if I have Model1 with O2O to Model2 and create a Model2 object with pk = 1, then a Model1 object with model2_id = 1 will be created automatically. Then, if I post data from DB to json, I will have two records for these objects. And if I try to load this data into the database using loaddata , it will fail, because the object for Model2 will be created twice, and this will cause a unique violation of the index and IntegrityError .
Has anyone found a reasonable solution for this?

ps
I am using Django 1.3.7

+7
python django
source share
4 answers

I did something similar, not with JSON, but with xml, and my django is 1.7, so maybe it does not work for you.

  • You can use natural keys when you reference serialized objects. This will prevent the elements from mixing if the index is already in use by another objject.
  • You can use dependencies to determine serialization order (and therefore deserialization).

Perhaps similar posts such as this one are also helpful.

+4
source share

When you flush your data, make sure you use the --natural argument:

 python manage.py dumpdata myapp --indent=4 --natural 

https://docs.djangoproject.com/en/dev/ref/django-admin/#django-admin-option---natural

It looks deprecated in 1.7 for - natural-foreign

+1
source share

Ultimately, you can use the South, which simplifies and facilitates data migration:

http://south.readthedocs.org/en/latest/about.html

Starting with Django 1.6, the new migration module will replace the old database commands and make the south obsolete.

0
source share

Indeed, O2O relationships can be tricky if you want to use commands like dumpdata and loaddata , for example, to back up and restore select objects in your database.

We have a similar problem with our software, and I found that a possible working solution would be to override the save() method on django.core.serializers.base.DeserializedObject to actually get the descriptor the moment before the "double " an object. At this point, you can drop the default O2O relationship created by Django and let the infrastructure save the new one or update it with the saved values ​​in your XML or JSON file.

You will need to put the rewritten method somewhere Django picks up before the loaddata command is loaddata . One possibility is to create your own command, which in turn calls loaddata . In the command module, you set an override. The following information about this decision is implied:

  • Tested with Django 1.8.x
  • Our O2O field is tied to the Django User model
  • For simplicity, I will call the O2O Attached field in this example.

 # Overrides deserialization to affect OneToOneFields for Users correctly import django.core.serializers.base from django.contrib.auth.models import User from your.attached.models import Attached #model with O2O field to User _original_save = django.core.serializers.base.DeserializedObject.save def save(self, *args, **kwargs): if isinstance(self.object, Attached): # if the user in question has an attached object, delete it user = User.objects.get(pk=self.object.user_id) if hasattr(user, 'attached'): user.attached.delete() # use the built-in function for all other cases _original_save(self, *args, **kwargs) django.core.serializers.base.DeserializedObject.save = save 

You can change the above code instead of deleting the existing object, updating it if you in the if hasattr(...) avoid deleting, update the existing object with the values ​​coming from your serialized object, and skip the call to _original_save() . This will make the code a little more model-bound, although you may have to determine which fields to update an existing object. The solution shown above does not make assumptions about the content of the model.

0
source share

All Articles