Python Django夹具和OneToOneField
如上所述,将自动为与其他模型具有OneToOne关系的模型创建对象。所以,如果我将带有O2O的Model1设置为Model2,并将创建带有pk=1的Model2的对象,那么将自动创建带有Model2_id=1的Model1的对象。然后,如果我将数据从DB转储到json,那么这些对象将有两条记录。如果我尝试使用Python Django夹具和OneToOneField,python,django,Python,Django,如上所述,将自动为与其他模型具有OneToOne关系的模型创建对象。所以,如果我将带有O2O的Model1设置为Model2,并将创建带有pk=1的Model2的对象,那么将自动创建带有Model2_id=1的Model1的对象。然后,如果我将数据从DB转储到json,那么这些对象将有两条记录。如果我尝试使用loaddata将此数据加载到DB,则会失败,因为Model2的对象将创建两次,并且会导致唯一索引冲突和IntegrityError 有人找到了解决这个问题的合理方法吗 p、 s. 我使用D
loaddata
将此数据加载到DB,则会失败,因为Model2的对象将创建两次,并且会导致唯一索引冲突和IntegrityError
有人找到了解决这个问题的合理方法吗 p、 s.
我使用Django 1.3.7您最终可能会使用South,这使得数据迁移既简单又强大:
Django 1.6附带了一个新的数据库命令,它将取代旧的数据库命令,并使South变得过时。我做了类似的事情,不是用JSON而是用xml,我的Django是1.7,所以它可能不适合您
类似的帖子也可能有帮助。当您转储数据装置时,请确保使用--natural参数:
python manage.py dumpdata myapp --indent=4 --natural
在1.7中,O2O似乎被弃用了,因为它是自然外来的。事实上,如果您想使用
dumpdata
和loaddata
等命令来备份和恢复数据库中的选定对象,O2O关系可能会变得棘手
我们的软件也有类似的问题,我发现一个可行的解决方案是覆盖django.core.serializers.base.DeserializedObject
上的save()
方法,以便在保存“double”对象之前获得一个句柄。此时,您可能会决定放弃Django创建的默认O2O关系,让框架保存新的O2O关系,或者用XML或JSON文件中存储的值更新它
在执行loaddata
命令之前,您必须将覆盖方法放在Django拾取的某个位置。一种可能是创建自己的命令,该命令依次调用loaddata
。在命令模块中,安装覆盖。此解决方案包含以下详细信息:
- 使用Django 1.8.x进行测试
- 我们的O2O字段连接到Django
模型用户
- 为了简单起见,在本例中,我将调用附加的O2O字段
attached
如果您在
if hasattr(…)
子句中避免删除,使用来自序列化对象的值更新现有对象,并跳过对\u original\u save()
的调用,则可以修改上述代码,而不是删除现有对象。不过,这将使代码与模型更紧密地联系在一起,因为您可能必须定义要在现有对象上更新的字段。上面显示的解决方案不对模型的内容进行任何假设。您找到解决方案了吗?如果必须更新django,我建议您进行更新,因为您认为转储数据中不会有多个对象,也不会多次创建。你能告诉我们转储数据给你什么吗?以及loaddata的错误?同意@Rohan。你确定他们的数据库中没有数据吗?你还确定这不仅仅是索引的问题吗?相关:迁移将随1.7。。。但是我认为他们在这种情况下没有帮助(南方也不会)。你能告诉我迁移将随1.7而来这一事实的来源吗?我们在上对此进行了一些讨论,在上有一个kickstarter项目从南方作者那里陈述了这一点。我在1.7 alpha版本中测试了它,但是由于第一个链接中提到的bug还没有完全解决,所以它对我来说还不起作用。在我写这篇文章的时候,Django还没有发布1.6,所以我想你可能打错了Django版本号no,我实际上使用的是最新的alpha版本1.7
# 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