由于内容类型冲突,我无法将 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
manage.py dumpdata --natural
将使用更持久的外键表示。在 django 中,它们被称为“自然键”。例如:
Permission.codename 用于 Permission.id
User.username 用于 User.id
阅读更多:natural keys section in "serializing django objects"
dumpdata
的其他一些有用参数:
--indent=4 使其易于阅读。
-e 会话排除会话数据
-e admin 排除管理站点上的管理操作历史记录
-e contenttypes -e auth.Permission 排除在 syncdb 期间每次从架构自动重新创建的对象。仅将它与 --natural 一起使用,否则您最终可能会得到错误对齐的 id 编号。
这里的答案都是旧的......截至2017年,最好的答案是:
manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4
是的,这真的很烦人。有一段时间,我通过在加载夹具之前对 contenttypes 应用程序执行“manage.py reset”来解决它(以摆脱与转储版本不同的自动生成的 contenttypes 数据)。那行得通,但最终我厌倦了麻烦并完全放弃了固定装置,转而支持直接的 SQL 转储(当然,这样你就失去了数据库的可移植性)。
更新 - 最好的答案是使用 --natural
标志到 dumpdata
,如下面的答案所述。当我写这个答案时,那个标志还不存在。
创建夹具时尝试跳过内容类型:
./manage.py dumpdata --exclude contenttypes > fixture.json
它在单元测试的类似情况下对我有用,您对内容类型的洞察力真的很有帮助!
我没有使用 MySQL,而是将一些数据从实时服务器导入 sqlite。在执行 loaddata
之前清除 contenttypes
应用程序数据起到了作用:
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()
接着
python manage.py loaddata data.json
我已经在我的测试用例中解决了这个问题,方法是在加载我的转储文件之前从单元测试中重置 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
。
您需要使用自然键来表示任何外键和多对多关系。此外,排除 sessions
应用程序中的 session
表和 admin
应用程序中的 logentry
表可能是个好主意。
姜戈 1.7+
python manage.py dumpdata --natural-foreign --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json
姜戈 <1.7
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
python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth.Permission --exclude=admin.logentry --exclude=sessions.session --indent 4 > initial_data.json
这对我有用。在这里,我排除了除实际模型之外的所有内容。
如果您看到除您创建的模型之外的任何其他模型,您可以安全地排除这些模型。这种方法的一个缺点是您在日志数据和身份验证数据上松散了。
./manage.py dumpdata app.Model --natural-foreign
将改变
"content_type": 123
至
"content_type": [
"app_label",
"model"
],
夹具现在适用于 TestCase
真的,真的很烦人..我每次都被这个咬伤。
我尝试使用 --exclude contenttypes 和 --natural 转储数据,但我总是遇到问题..
最适合我的方法是在 syncdb 之后执行 truncate table django_content_type;
,然后加载数据。
当然,对于 initial_data.json 自动加载,你是个失败者。
Django 2.2.5
python manage.py dumpdata --exclude=contenttypes > datadump.json
它帮助了我
我将给出我刚刚想出的另一个可能的答案。也许它会帮助OP,也许它会帮助其他人。
我有一个多对多关系表。它有一个主键和其他表的两个外键。我发现,如果我在夹具中有一个条目,其两个外键与表中已有的另一个具有不同 pk 的条目相同,它将失败。 M2M 关系表对两个外键具有“唯一性”。
因此,如果 M2M 关系正在中断,请查看它添加的外键,查看您的数据库以查看该对 FK 是否已列在不同的 PK 下。
我以前有时也遇到过类似的错误。事实证明,我试图在创建必要的表之前加载固定装置。所以我做了:
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py loaddata fixtures/initial_data.json
它就像一个魅力
我尝试了上面的所有方法,对我没有任何作用。我必须排除完整的身份验证模型并且工作正常。
python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
在我的例子中,我已经从 auth
(./manage.py dumpddata auth > fixtures/auth.json
) 中转储了数据,以便将夹具用于测试目的。
开发继续进行,我删除了我在 models.py
中定义的大部分模型,这就是我开始看到这个烦人的问题的时候。
我的解决方案是再次重新生成 auth.json 夹具。这个删除了 auth.permission
中与我拥有的旧模型相关的许多条目。
我已经通过添加我的测试 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()
-e contenttypes -e auth.permission
与--natural
一起使用?我只是尝试不使用--natural
选项并且它有效。 documentation here 还表示,如果 DUMPINGauth.permission
和contenttypes
应使用此选项。ContentType
和Permission
不能保证获得与以前相同的 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
。