在Django中加载包含内容类型自然键的fixtures时出现类型错误

5 投票
1 回答
1782 浏览
提问于 2025-04-16 11:27

我在把我的一个模型导出成数据文件时,使用了 --natural 这个选项,这样在部署的时候就不会遇到内容类型 ID 的问题。结果如下:

{
     "pk": 1, 
     "model": "seo.opportunitymetadatamodel", 
     "fields": {
         "_content_type": [
              "opportunity", 
              "jobopportunity"
         ], 
         "og_description": "", 
         "description": "", 
         "title": "test", 
         "keywords": "", 
         "og_title": "", 
         "heading": ""
     }
}

但是当我尝试把这个数据文件加载回去时,出现了以下错误:

Problem installing fixture 'seo/fixtures/initial_data.json': Traceback (most recent call last):
  File "/Users/xx/dev/envs/xx/lib/python2.6/site-packages/django/core/management/commands/loaddata.py", line 167, in handle
    for obj in objects:
  File "/Users/xx/dev/envs/xx/lib/python2.6/site-packages/django/core/serializers/json.py", line 38, in Deserializer
    for obj in PythonDeserializer(simplejson.load(stream), **options):
  File "/Users/xx/dev/envs/xx/lib/python2.6/site-packages/django/core/serializers/python.py", line 84, in Deserializer
    Model = _get_model(d["model"])
TypeError: string indices must be integers, not str

看起来这个方法不接受字符串来加载。我是不是漏掉了什么?

1 个回答

4

我现在只能猜测,但根据我查看Django的源代码和你的错误信息,我觉得你的数据格式可能有问题。你发的例子,是文件的全部内容吗?如果是的话,我觉得你需要把那个模型放在一个列表里,像这样(注意外面的括号):

[
  {
    "pk": 1, 
    "model": "seo.opportunitymetadatamodel", 
    "fields": {
      "_content_type": [
        "opportunity", 
        "jobopportunity"
      ], 
      "og_description": "", 
      "description": "", 
      "title": "test", 
      "keywords": "", 
      "og_title": "", 
      "heading": ""
    }
  }
]

为什么呢?因为Django成功解析了JSON数据后,这些数据会传给Python的反序列化器。这个反序列化器会像这样遍历数据:

82      for d in object_list:
83          # Look up the model and starting build a dict of data for it.
84          Model = _get_model(d["model"])

http://code.djangoproject.com/browser/django/trunk/django/core/serializers/python.py#L82

现在想象一下,object_list是一个JSON对象(相当于Python的字典),遍历它只会得到键,也就是pk, model, field这些。在第84行,Django执行了_get_model(d["model"]),也就是说,它用字符串"model"作为索引去查找另一个字符串,可能是pk(这是object_list中的第一个元素)。这就导致了类型错误。

object_list是一个真正的列表时,遍历它会得到字典,这些字典可以用字符串来索引。

撰写回答