8

如此处所述对象是为与其他模型具有 OneToOne 关系的模型自动创建的。因此,如果我将 Model1 与 O2O 连接到 Model2,并将创建 pk=1 的 Model2 对象,那么将自动创建具有 model2_id=1 的 Model1 对象。然后,如果我将数据从 DB 转储到 json,我将有这些对象的两条记录。如果我尝试使用 - 将这些数据加载到 DB 中,loaddata它将失败,因为 Model2 的对象将被创建两次,这将导致唯一索引冲突和IntegrityError.
有没有人为此找到理智的解决方案?

ps
我使用 Django 1.3.7

4

4 回答 4

4

我做了类似的事情,不是用 JSON 而是用 xml,我的 django 是 1.7,所以也许它不适合你。

  1. 引用序列化对象时可以使用自然键。如果索引已被其他对象使用,这将防止混淆项目。
  2. 您可以使用依赖项来定义序列化(以及反序列化)的顺序。

也许像这样的类似帖子也有帮助。

于 2013-11-01T23:21:37.813 回答
2

当您转储数据固定装置时,请确保使用 --natural 参数:

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

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

它看起来在 1.7 中被弃用了 --natural-foreign

于 2013-11-04T21:13:01.267 回答
0

您最终可能会使用 South,它使数据迁移既简单又强大:

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

随着 Django 1.6 的到来,一个新的迁移模块将取代旧的数据库命令并使 South 过时。

于 2013-10-30T09:00:16.163 回答
0

实际上,如果您想使用dumpdata和之类的命令loaddata来备份和恢复数据库中的选定对象,O2O 关系可能会变得很棘手。

我们的软件也有类似的问题,我发现一个可能的工作解决方案是覆盖该save()方法,django.core.serializers.base.DeserializedObject以便在保存“双”对象之前实际获得句柄。此时,您可能决定丢弃 Django 创建的默认 O2O 关系,让框架保存新关系或使用 XML 或 JSON 文件中存储的值更新它。

loaddata不过,在执行命令之前,您必须将覆盖的方法放在 Django 获取的某个位置。一种可能性是创建自己的命令,然后调用loaddata. 在命令模块中,您安装覆盖。暗示了有关此解决方案的以下详细信息:

  • 用 Django 1.8.x 测试
  • 我们的 O2O 领域是附加到 DjangoUser模型的
  • 为了在这个例子中简单起见,我将调用附加的 O2O 字段Attached

# 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

您可以修改上面的代码,而不是删除现有对象,如果您在if hasattr(...)子句中避免删除,使用来自序列化对象的值更新现有对象并跳过对_original_save(). 不过,这将使代码与模型更加相关,因为您可能必须定义要在现有对象上更新哪些字段。上面显示的解决方案对模型的内容没有任何假设。

于 2015-12-15T11:16:46.307 回答