如何解决Django中加载包含Content_type自然键的fixtures导致的类型错误

42 阅读1分钟

在使用Django的--natural选项转储模型到fixture时,可能会遇到Content_typ ID问题。

例如,假设有一个名为OpportunityMetaDataModel的模型,它包含一个_content_type字段,该字段存储了模型的Content_type ID。当使用--natural选项转储OpportunityMetaDataModel模型时,结果是:

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

当尝试加载此fixture时,可能会遇到以下错误:

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. 解决方案 为了解决此问题,需要将模型包装在一个列表中,如下所示:
[  {    "pk": 1,     "model": "seo.opportunitymetadatamodel",     "fields": {      "_content_type": [        "opportunity",         "jobopportunity"      ], 
      "og_description": "", 
      "description": "", 
      "title": "test", 
      "keywords": "", 
      "og_title": "", 
      "heading": ""
    }
  }
]
>>> d = [{...     "pk": 1, ...     "model": "seo.opportunitymetadatamodel", ...     "fields": {...         "_content_type": [...              "opportunity", ...              "jobopportunity"...         ], 
...         "og_description": "", 
...         "description": "", 
...         "title": "test", 
...         "keywords": "", 
...         "og_title": "", 
...         "heading": ""
...     }
... }]
>>> import json
>>> json.dumps(d)
'[{"pk": 1, "model": "seo.opportunitymetadatamodel", "fields": {"_content_type": ["opportunity", "jobopportunity"], "og_description": "", "description": "", "title": "test", "keywords": "", "og_title": "", "heading": ""}}]'

当Django解析JSON数据时,它会将数据传递给python反序列化器。反序列化器按如下方式迭代数据:

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

如果object_list是一个json对象,迭代只会获取键,在这种情况下可能是pk、model和field。在第84行,Django执行_get_model(d["model"]),即使用字符串“model”作为另一个字符串(可能是object_list中的第一个元素pk)的索引。这是一个类型错误。

当object_list是一个实际列表时,迭代它将返回字典,这些字典可以通过字符串索引。