【问题标题】:Django fixtures and OneToOneFieldDjango 固定装置和 OneToOneField
【发布时间】:2013-09-02 12:39:27
【问题描述】:

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

附言
我使用 Django 1.3.7

【问题讨论】:

  • 您找到解决方案了吗?
  • 如果有可能,我建议您更新 django
  • 不要以为dump数据中会有多个对象或者创建了多次。你能告诉我们转储数据给你什么吗?还有loaddata的错误?
  • 同意@Rohan。你确定他们的数据库中没有数据吗?
  • 您是否也确定这不仅仅是索引的问题?相关:stackoverflow.com/a/19136200/785400

标签: python django


【解决方案1】:

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

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

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

【讨论】:

  • 在我写这篇文章的时候,Django 还没有发布 1.6,所以我想你可能打错了 Django 版本号
  • 不,我使用的是最新的 alpha 版本 1.7
【解决方案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 弃用了

【讨论】:

    【解决方案3】:

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

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

    随着 Django 1.6,新的 migrations module 将替换旧的数据库命令并使 South 过时。

    【讨论】:

    • 1.7 版本即将进行迁移...但我认为它们在这种情况下没有帮助(南方也不会)
    • 你能告诉我迁移是在 1.7 中出现的事实的来源吗?
    • 我们在code.djangoproject.com/ticket/21142 上进行了一些讨论,并且有一个来自南方作者的kickstarter 项目在kickstarter.com/projects/andrewgodwin/… 上说明了相同的内容。我在 1.7 alpha 版本中对其进行了测试,但是由于第一个链接中提到的错误尚未完全解决,因此对我来说并没有解决。
    【解决方案4】:

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

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

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

    • 用 Django 1.8.x 测试
    • 我们的 O2O 字段附加到 Django User 模型
    • 为简单起见,本例中,我将附加的 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()。不过,这将使代码与模型更加相关,因为您可能必须定义要在现有对象上更新哪些字段。上面显示的解决方案对模型的内容没有任何假设。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-10
      • 2015-07-28
      • 2019-06-27
      • 1970-01-01
      相关资源
      最近更新 更多