在Django中加载灯具时内容类型出现问题


104

由于内容类型冲突,我无法将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

问题是建议的解决方法是转储我已经在做的contenttypes应用!是什么赋予了?如果有什么不同,我确实有一些自定义模型权限,如此处记录:http : //docs.djangoproject.com/en/dev/ref/models/options/#permissions

Answers:


148

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

  • Permission.codename 被用来支持 Permission.id
  • User.username 被用来支持 User.id

阅读更多:“序列化django对象”中的自然键部分

其他一些有用的参数dumpdata

  • --indent=4 使它易于阅读。
  • -e sessions 排除会话数据
  • -e admin 排除管理员网站上管理员操作的历史记录
  • -e contenttypes -e auth.Permission排除在每次期间从模式自动重新创建的对象syncdb。请仅将其与一起使用--natural,否则可能会导致ID编号不一致。

1
@skyjur为什么总是-e contenttypes -e auth.permission与一起使用--natural?我只是尝试了没有--natural选择,它的工作。同样,这里文档说,如果DUMPING auth.permission和,则应该使用此选项contenttypes
wlnirvana 2014年

6
@winirvana,因为从头开始并执行syncdb后,新创建的ContentTypePermission不能保证获得与以前相同的ID。您的数据转储包含可能引用另一个数据库的ID,这些数据库将在其中装载数据。由于以下原因之一,它可能对您有用:1)您的数据没有对这些对象的任何引用2)保留了Permission / ContentTypes的原始ID 3)您的loaddata成功,但实际上由于对象而损坏了数据指的是错误的物体,而您对此一无所知
2015年

12
--natural现在不推荐使用Flag ,而赞成--natural-foreign(和--natural-primary
frnhr

16
最终命令可能是:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Paolo

4
--natural现在已被完全删除,而不仅仅是弃用了。使用--natural-foreign--natural-primary代替。
法学徒'18年

35

是的,这真令人讨厌。有一段时间,我通过在加载夹具之前在contenttypes应用程序上执行“ manage.py reset”来解决该问题(摆脱了与转储版本不同的自动生成的contenttypes数据)。那行得通,但最终我完全不喜欢直接的SQL转储(我当然会失去数据库的可移植性),使我烦恼并完全放弃了固定装置。

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


3
我也遇到了这个问题,重置contenttypes应用程序也对我有用。谢谢你的提示!
Beau:

您如何重置它们?在测试用例类中?请给我一个例子
Oleg Tarasenko 09年

4
我不使用夹具进行单元测试,一般来说,我会在setup()方法中使用ORM创建测试数据,因为它更容易与测试保持同步。因此,我从来没有在TestCase类中执行此操作,尽管我确定如果您在Django的TestCase类的代码中戳一下,您可以弄清楚如何在syncdb之后以及在将夹具加载到子类之前进行重置。对我而言,它只是bash脚本中“ ./manage.py loaddata my_fixture”之前的“ ./manage.py reset contenttypes”。
卡尔·梅耶

32

创建装置时,请尝试跳过内容类型:

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

在类似的单元测试环境中,它对我很有用,您对内容类型的见解确实有所帮助!


31

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

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

11

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

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()。
Barney

在自定义管理命令的句柄中,它可能最有效。
Barney

10

通过在加载转储文件之前从单元测试中重置contenttypes应用程序,我已经在测试用例中解决了此问题。卡尔已经使用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装置包含与其余测试数据相对应的contenttypes应用程序转储。通过在加载之前重置应用程序,可以防止重复密钥IntegrityError


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

这对我有用。在这里,我排除了所有支持实际模型的东西。

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

6

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

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 <1.7

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

根据Django文档--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


2

的Django 2.2.5

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

它帮助了我


这将提高问题的时候loaddata,也许在新的数据库的contentType不匹配
周洋

1

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

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

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


1

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

我试图用--exclude contenttypes和--natural来转储数据,我总是遇到问题。

最适合我的方法是truncate table django_content_type;在syncdb和THEN加载数据之后简单地执行一个操作。

当然,对于initial_data.json自动加载,您将陷入困境。


对我来说,在loaddata之前截断表只会导致不同的错误。这项技术没有运气。
黑客2012年

1

有时我也遇到过类似的错误。原来,我试图在创建必要的表之前加载灯具。所以我做了:

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

它像魅力一样运作


0

就我而言,我已转储了auth./manage.py dumpddata auth > fixtures/auth.json)中的数据以将灯具用于测试目的。

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

我的解决方案是再次重新生成auth.json固定装置。这个已经删除了很多auth.permission与我的旧模型相关的条目。


0

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

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.