【发布时间】:2011-07-14 17:56:24
【问题描述】:
我最近尝试将一些固定装置加载到我的数据库中。当我运行服务器并加载各种页面时,虽然我得到了错误:
Caught DoesNotExist while rendering: ContentType matching query does not exist.
我尝试过运行 syncdb,并分别重置每个应用程序,但没有任何运气。如何消除此错误?
【问题讨论】:
标签: django content-type
我最近尝试将一些固定装置加载到我的数据库中。当我运行服务器并加载各种页面时,虽然我得到了错误:
Caught DoesNotExist while rendering: ContentType matching query does not exist.
我尝试过运行 syncdb,并分别重置每个应用程序,但没有任何运气。如何消除此错误?
【问题讨论】:
标签: django content-type
如果您查看灯具内部,每个灯具都有三个根字段:PK、fields(这是该表中第 PK 条目的一组字段)和 model,其中包含appname.modelname,ORM 从中派生表信息。
Django 通过 ContentType 引擎查找 appname.modelname 以确定将数据放入哪个表。
您的朋友给了您至少一个夹具,其中 model 字段的内容与您数据库中的任何实际模型都不匹配。这可能是拼写错误、误解、型号或应用程序名称的更改,或任何数量的故障。但是夹具不对应于您项目中的任何模型,夹具导入器告诉您,它无法将模型的指定名称与项目 ContentType 表中的任何名称匹配。
解决方法可能很简单,只需确定表格应该具有的 ContentType,然后打开夹具并在 model: 行上进行大规模搜索和替换。
编辑:
这是一个长期(长期!)过期的编辑。如果您要 dumpdata 包含通用数据或对其他地方的通用表的引用,您必须(我真的无法强调您必须有多少)学习dumpdata --natural 标志。它不是按数字保存 contentType 信息,而是按名称保存,从而使重新加载数据库变得更加容易且不易出错。
【讨论】:
--natural 标志已被弃用。相反,您可以使用--natural-foreign
您可以手动检查数据库中的每个 ContentType 表,或者:
或者您可以使用其中一种 Django 迁移工具:
可访问的django-evolution
或者更复杂的south
【讨论】:
我发现了导致此错误的不同原因,我想补充一下以防万一这对其他人有帮助。对我来说导致此问题的原因是我创建了一个具有特定权限的组,然后卸载了该组中引用的应用程序。
具体来说,我曾经安装过reversion,并创建了一个名为“Site Editor”的组,该组授予用户创建、编辑和删除修订的权限。后来我卸载了修订版,但是当我运行“dumpdata”命令时,组权限仍然存在:
[
{
"fields": {
"name": "Site Editor",
"permissions": [
[
"add_logentry",
"admin",
"logentry"
],
[
"change_logentry",
"admin",
"logentry"
],
[
"delete_logentry",
"admin",
"logentry"
],
[
"add_group",
"auth",
"group"
],
[
"change_group",
"auth",
"group"
],
[
"delete_group",
"auth",
"group"
],
[
"add_revision",
"reversion",
"revision"
],
[
"change_revision",
"reversion",
"revision"
],
[
"delete_revision",
"reversion",
"revision"
],
[
"add_version",
"reversion",
"version"
],
[
"change_version",
"reversion",
"version"
],
[
"delete_version",
"reversion",
"version"
],
[
"add_session",
"sessions",
"session"
],
[
"change_session",
"sessions",
"session"
],
[
"delete_session",
"sessions",
"session"
],
[
"add_site",
"sites",
"site"
],
[
"change_site",
"sites",
"site"
],
[
"delete_site",
"sites",
"site"
]
]
},
"model": "auth.group",
"pk": 2
}]
当我尝试运行“loaddata”命令时,我一直遇到这个错误:
django.core.serializers.base.DeserializationError:
Problem installing fixture '/Users/me/Documents/Sites/project/path/fixtures/configuration.json':
ContentType matching query does not exist.
我的解决方案是简单地删除夹具本身中对 reversion 和版本的任何引用,如下所示:
[
{
"fields": {
"name": "Site Editor",
"permissions": [
[
"add_logentry",
"admin",
"logentry"
],
[
"change_logentry",
"admin",
"logentry"
],
[
"delete_logentry",
"admin",
"logentry"
],
[
"add_group",
"auth",
"group"
],
[
"change_group",
"auth",
"group"
],
[
"delete_group",
"auth",
"group"
],
[
"add_session",
"sessions",
"session"
],
[
"change_session",
"sessions",
"session"
],
[
"delete_session",
"sessions",
"session"
],
[
"add_site",
"sites",
"site"
],
[
"change_site",
"sites",
"site"
],
[
"delete_site",
"sites",
"site"
]
]
},
"model": "auth.group",
"pk": 2
}]
然后我可以毫无问题地导入夹具。
【讨论】:
从 django 1.7 开始,dumpdata 选项发生了变化: 见http://polarhome.com:753/doc/python-django-doc/html/topics/serialization.html
所以你一个用途:
python manage.py dumpdata --natural-foreign --natural-primary --exclude > my_fixture.json
python manage.py loaddata my_fixture.json
另外,也可以解决根本原因:确保源数据库和目标数据库中的内容类型匹配。我在数据库之间移动数据时遇到了同样的错误,其中 db1 仍然具有来自同时已被删除的应用程序的内容类型。在应用程序从不存在的 db2 中导入这些会导致此错误消息。
在这种情况下,在数据库级别编辑 db1 中的 django_content_type 表并删除 django 应用程序中不再使用的内容类型。 然后再次将数据迁移或复制到 db2。
如果内容类型在其他表中被引用,您可能需要先将其删除,或者使用 DROP CASCADE 命令(有风险!)。
警告:在数据库级别进行编辑是一项有风险的业务,因此请务必在参与之前进行备份,并且不要在生产数据库上执行此操作。
根据数据库类型,您需要使用不同的工具进行编辑。
mysql -> [MySQLWorkBench][1]
postgres -> [pgAdmin][2]
SQLite -> [SQLite Browser][3]
【讨论】:
在某些情况下,当您的夹具包含对不存在的模型的引用时会导致此错误,因为它尚未安装或它的应用程序尚未添加到您的 INSTALLED_APPS。不幸的是,Django 的错误信息在追踪它时毫无用处。
如果您编辑django/db/models/query.py 中的Queryset.get 方法以打印出传递的*args 和**kwargs,您将收到更有用的错误消息,例如:
DeserializationError: Problem installing fixture ... ContentType matching query does not exist. args=() kwargs={'model': u'somenewmodel', 'app_label': u'somenewapp'}
然后您可以检查此模型/应用程序是否已安装或从您的夹具中删除这些记录。
【讨论】:
您最近是否从 mysql 改为使用 postgres?
当查询contenttypes 时:
entry_content_type = ContentType.objects.get(
app_label="entries", model="Entry"
)
这失败了,因为在postgres; app_label 和 model 都是小写字段。所以请使用__iexact 字段查找,它会忽略大小写。
entry_content_type = ContentType.objects.get(
app_label__iexact="entries", model__iexact="Entry"
)
【讨论】:
经过大量试验后,这对我有用。我在组和日志方面遇到了很多麻烦。
在 sqllite 上,启动服务器,进入管理员并删除所有组。然后在shell中输入以下内容:
python manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission -e admin.Logentry > datadump_3.json
在 settings.py
python manage.py loaddata datadump_3.json
【讨论】: