【问题标题】:Problems with contenttypes when loading a fixture in Django在 Django 中加载固定装置时出现内容类型问题
【发布时间】:2010-10-25 14:59:27
【问题描述】:

由于内容类型冲突,我无法将 Django 固定装置加载到我的 MySQL 数据库中。首先,我尝试只从我的应用程序中转储数据,如下所示:

./manage.py dumpdata escola > fixture.json

但我总是遇到缺少外键的问题,因为我的应用程序“escola”使用了其他应用程序中的表。我一直在添加其他应用程序,直到我做到这一点:

./manage.py dumpdata contenttypes auth escola > fixture.json

现在问题是当我尝试将数据加载为测试夹具时出现以下约束冲突:

IntegrityError: (1062, "Duplicate entry 'escola-t23aluno' for key 2")

问题似乎在于 Django 试图动态地重新创建具有不同主键值的内容类型,这些主键值与夹具中的主键值冲突。这似乎与此处记录的错误相同:http://code.djangoproject.com/ticket/7052

问题是推荐的解决方法是转储我已经在做的内容类型应用程序!?是什么赋予了?如果有什么不同,我确实有一些自定义模型权限,如下所述:http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

【问题讨论】:

    标签: mysql django django-models fixtures mysql-error-1062


    【解决方案1】:

    manage.py dumpdata --natural 将使用更持久的外键表示。在 django 中,它们被称为“自然键”。例如:

    • Permission.codename 用于支持Permission.id
    • User.username 用于支持User.id

    阅读更多:natural keys section in "serializing django objects"

    dumpdata 的其他一些有用参数:

    • --indent=4 使其易于阅读。
    • -e sessions 排除会话数据
    • -e admin 排除管理站点上的管理操作历史记录
    • -e contenttypes -e auth.Permission 排除在 syncdb 期间每次从模式中自动重新创建的对象。只能将它与 --natural 一起使用,否则您可能会得到错误对齐的 id 编号。

    【讨论】:

    • @skyjur 为什么总是使用-e contenttypes -e auth.permission--natural?我刚刚尝试不使用--natural 选项并且它有效。 documentation here 还说如果 DUMPING auth.permissioncontenttypes 应该使用这个选项。
    • @winirvana 因为在您从头开始并执行syncdb 之后,新创建的ContentTypePermission 不能保证获得与以前相同的ID。您的数据转储包含可能引用另一个数据库上您将加载数据的不同对象的 ID。由于以下原因之一,它可能对您有用:1)您的数据没有对这些对象的任何引用 2)Permission/ContentTypes 的原始 id 被保留 3)您的 loaddata 成功但实际上由于对象而导致数据损坏引用了错误的对象而你还不知道
    • 标志 --natural 现已弃用,取而代之的是 --natural-foreign(和 --natural-primary
    • 最终命令可能是:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
    • --natural 现在已被完全删除,而不仅仅是弃用。请改用--natural-foreign--natural-primary
    【解决方案2】:

    这里的答案都是旧的......截至 2017 年,最佳答案是:

    manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4
    

    【讨论】:

      【解决方案3】:

      是的,这真的很烦人。有一段时间,我通过在加载夹具之前对 contenttypes 应用程序执行“manage.py reset”来解决它(以摆脱与转储版本不同的自动生成的 contenttypes 数据)。那行得通,但最终我厌倦了麻烦并完全放弃了固定装置,转而支持直接的 SQL 转储(当然,这样你就失去了数据库的可移植性)。

      更新 - 最好的答案是使用--natural 标志到dumpdata,如下面的答案所述。当我写这个答案时,那个标志还不存在。

      【讨论】:

      • 我也遇到了这个问题,重置 contenttypes 应用程序也对我有用。感谢您的提示!
      • 你是如何重置它们的?在测试用例类中?请给我一个例子
      • 我不使用固定装置进行单元测试,我通常在 setup() 方法中使用 ORM 创建测试数据,因为它更容易与测试保持同步。所以我从来不需要在 TestCase 类中这样做,尽管我确信如果你在 Django 的 TestCase 类的代码中四处寻找,你可以弄清楚如何在 syncdb 之后和在子类中加载夹具之前进行重置。对我来说,它只是“./manage.py loaddata my_fixture”之前的 bash 脚本中的“./manage.py reset contenttypes”。
      【解决方案4】:

      在创建夹具时尝试跳过内容类型:

      ./manage.py dumpdata --exclude contenttypes > fixture.json
      

      它在单元测试的类似情况下对我有用,您对内容类型的洞察力真的很有帮助!

      【讨论】:

        【解决方案5】:

        我没有使用 MySQL,而是将一些数据从实时服务器导入到 sqlite。在执行loaddata 之前清除contenttypes 应用数据就可以了:

        from django.contrib.contenttypes.models import ContentType
        ContentType.objects.all().delete()
        quit()
        

        然后

        python manage.py loaddata data.json
        

        【讨论】:

        • django.core.exceptions.ImproperlyConfigured:请求设置 INSTALLED_APPS,但未配置设置。您必须在访问设置之前定义环境变量 DJANGO_SETTINGS_MODULE 或调用 settings.configure()。
        • 在自定义管理命令的句柄中可能效果最好。
        【解决方案6】:

        我已经在我的测试用例中解决了这个问题,方法是在加载我的转储文件之前从单元测试中重置 contenttypes 应用程序。 Carl 已经使用 manage.py 命令提出了这个建议,而我只使用 call_command 方法做同样的事情:

        >>> from django.core import management
        >>> management.call_command("flush", verbosity=0, interactive=False)
        >>> management.call_command("reset", "contenttypes", verbosity=0, interactive=False)
        >>> management.call_command("loaddata", "full_test_data.json", verbosity=0)
        

        我的full_test_data.json 夹具包含与其余测试数据相对应的内容类型应用转储。通过在加载之前重置应用程序,它可以防止重复键IntegrityError

        【讨论】:

          【解决方案7】:

          您需要使用自然键来表示任何外键和多对多关系。此外,排除sessions 应用程序中的session 表和admin 应用程序中的logentry 表可能是个好主意。

          Django 1.7+

          python manage.py dumpdata --natural-foreign --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
          

          Django

          python manage.py dumpdata --natural --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
          

          根据Django documentation--natural 在 1.7 版本中已被弃用,因此应使用选项--natural-foreign

          您也可以省略此对象的序列化数据中的主键,因为它可以在反序列化期间通过传递--natural-primary 标志来计算。

          python manage.py dumpdata --natural-foreign --natural-primary --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
          

          【讨论】:

            【解决方案8】:
            python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth.Permission --exclude=admin.logentry --exclude=sessions.session --indent 4 > initial_data.json
            

            这对我有用。在这里,我排除了除实际模型之外的所有内容。

            • 如果您看到除您创建的模型之外的任何其他模型,您可以安全地排除这些模型。这种方法的一个缺点是您在日志数据和身份验证数据上松散了。

            【讨论】:

              【解决方案9】:
              ./manage.py dumpdata app.Model --natural-foreign
              

              会改变

                "content_type": 123
              

                "content_type": [
                  "app_label",
                  "model"
                ],
              

              夹具现在适用于TestCase

              【讨论】:

                【解决方案10】:

                真的,真的很烦人..我每次都被这个咬伤。

                我尝试使用 --exclude contenttypes 和 --natural 转储数据,但总是遇到问题..

                最适合我的方法是在 syncdb 之后执行 truncate table django_content_type;,然后加载数据。

                当然,对于 initial_data.json 自动加载,你是个失败者。

                【讨论】:

                • 对我来说,在 loaddata 之前截断表只会导致不同的错误。这种技术不走运。
                【解决方案11】:

                Django 2.2.5

                python manage.py dumpdata --exclude=contenttypes > datadump.json
                

                它帮助了我

                【讨论】:

                • 加载数据时会出现问题,可能与新数据库中的内容类型不匹配
                【解决方案12】:

                我将给出我刚刚想到的另一个可能的答案。也许它会帮助 OP,也许它会帮助其他人。

                我有一个多对多关系表。它有一个主键和其他表的两个外键。我发现,如果我在夹具中有一个条目,其两个外键与表中已有的另一个条目相同,并且具有 不同的 pk,它将失败。 M2M 关系表对于两个外键具有“唯一性”。

                因此,如果 M2M 关系正在中断,请查看它添加的外键,查看您的数据库以查看该对 FK 是否已列在不同的 PK 下。

                【讨论】:

                  【解决方案13】:

                  我以前有时也遇到过类似的错误。事实证明,我试图在创建必要的表之前加载固定装置。所以我做了:

                  $ python manage.py makemigrations
                  $ python manage.py migrate
                  $ python manage.py loaddata fixtures/initial_data.json
                  

                  它就像一个魅力

                  【讨论】:

                    【解决方案14】:

                    我尝试了上面的所有方法,但没有任何效果。我必须排除完整的身份验证模型并且工作正常。

                    python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
                    

                    【讨论】:

                      【解决方案15】:

                      在我的例子中,我已经从 auth (./manage.py dumpddata auth > fixtures/auth.json) 中转储了数据,以便将夹具用于测试目的。

                      开发继续进行,我删除了我在models.py 中定义的大部分模型,这就是我开始看到这个烦人的问题的时候。

                      我的解决方案是再次重新生成 auth.json 夹具。这个删除了auth.permission 中与我拥有的旧模型相关的许多条目。

                      【讨论】:

                        【解决方案16】:

                        我已经通过添加我的测试 setUp 和 tearDown 来解决这个问题

                        from django.core import management
                        

                        =====

                        def setUp(self):
                            management.call_command("loaddata", "all-data.yaml", verbosity=0)
                            super(login_page_test, self).setUp()
                        
                        def tearDown(self):
                            management.call_command("flush", verbosity=0, interactive=False)
                            super(login_page_test, self).setUp()
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2016-09-16
                          • 1970-01-01
                          • 2011-12-14
                          • 1970-01-01
                          相关资源
                          最近更新 更多