【问题标题】:Feeding JSON results from MongoDB into Django Template view doesn't display dictionary values将 MongoDB 的 JSON 结果输入 Django 模板视图不显示字典值
【发布时间】:2015-02-06 10:53:58
【问题描述】:

我从 MongoDB 返回一个记录集,将其解析为 JSON 并将其推送到视图中,并尝试访问模板中每个记录的字典值。我可以打印记录(作为单独的记录),但我无法将每条记录的结构作为字典访问。我怎样才能获得这些价值观?

def index(request): 
    results = settings.vali_collection.find({'index': []  })
    json_docs = [json.dumps(doc, default=json_util.default) for doc in results]
    return render(request, 'db.html', {'results': json_docs[0:3]})

在我的模板中:

{% for result in results %}
    {{ result.name}}
    {{ result.items.name}}
{% endfor %}

我的 JSON 看起来像:

{"name": "Travel & Leisure", .., ..}

我可以使用{{record}} 打印模板中的记录,但是我如何将记录作为字典获取?我在模板中上面的内容不起作用并且什么也不返回。但是当我使用时:

{% for result in results %}
  {{ result}}
{% endfor %}

我可以将记录以 JSON 格式打印到屏幕上。如果我打印出 json_docs,我会得到以下信息:

['{"name": "random", "sector": "random"}',  {"name": "random", "sector": "random"}', {"name": "random", "sector": "random"}']

【问题讨论】:

  • results = settings.vali_collection.find({'index': [] }) 返回什么?

标签: python json mongodb


【解决方案1】:

如果 json 本身是字典,则需要嵌套循环。类似于以下内容:

   {%for i in gme%}

       {%for l, k in i.items%}
           <p>  {{l}}  {{k}} </p>
       {%endfor%}

   {%endfor%}

gme 看起来像这样: gme = [{"sdfje": 'sdfs',"sdfds": "sdf"},...]

输出是:

 sdfje sdfs

sdfds sdf 

使用json.loads(...) 而不是json.dumps

 json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)

    Serialize obj to a JSON formatted str 

 json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])

    Deserialize s (a str or unicode instance containing a JSON document) to a Python object using this conversion table.

你正在做的是将python字典序列化为JSON formatted str,所以你得到的是字符串而不是字典。

您需要反序列化,为此,您需要json.loads

如果您不能使用json.loads,正如您在 cmets 部分中所说,那么results 变量不是json string。也许这就是你要找的东西?尝试调试一下,看看results里面是什么

【讨论】:

  • 谢谢,但这是我尝试的第一件事。不知何故,模板没有将结果视为字典 - 因此我无法打印出键。
  • @Navonod 你能在return语句之前调试或打印json_docs的内容吗?
  • 我得到了一个字典列表
  • @Navonod 我刚刚检查了您打印的json_docs。它不是字典列表。 '{"name": "random", "sector": "random"}' 不是字典而是字符串。
  • @Navonod 您提供的甚至不是字符串列表。它的语法无效。你确定这是正确的打印信息吗?
【解决方案2】:

如果您使用PyMongo 2.8 find 返回一个可以切片的Cursor。这应该有效:

db.test.find()[20:25]

这也应该有效:

result = db.test.find()
...
sliced_result = result[20:25]

您不需要将结果转换为 JSON,您可以将 Cursor 转换为 list 并将其直接传递给模板,如下所示:

def index(request): 
    results = settings.vali_collection.find({'index': []})[:3]

    return render(request, 'db.html', {'results': list(results)})

您需要使用list(results) 来强制Cursor 执行查询。在您的模板中,您将有一个 dicts 列表,所以这应该可以工作:

{% for result in results %}
    {{ result.name }}
    {{ result.items.name }}
{% endfor %}

result 应该是dict。我看到的唯一问题是 items 是 Django 中的模板函数,这可能会使正在阅读您的模板的人感到困惑,并且会阻止您执行以下操作:

{% for result in results %}
    {% for attr_name, value in result.items %}
        {{ attr_name }}: {{ value }}
    {% endfor %}
{% endfor %}

内部 for 将显示 MongoDB 集合中文档的每个属性及其值。

如果您使用的是不允许切片的旧版 PyMongo,您可能需要执行以下操作:

def index(request): 
    results = settings.vali_collection.find({'index': []}).limit(3)

    return render(request, 'db.html', {'results': list(results)})

limit 限制Cursor 返回的结果数。

【讨论】:

    【解决方案3】:

    我相信模板中的result 不是你想的那样。让我们检查如下:

    在函数index(request)

    • results = settings.vali_collection.find({'index': [] }) 返回类似字典的对象列表。

    • json_docs = [json.dumps(doc, default=json_util.default) for doc in results] 返回 JSON 字符串 列表(不是字典)。

    所以稍后当您遍历子列表 json_docs[0:3] 时,您只是在遍历字符串列表,这就是您无法引用 .name.items 属性的原因。

    看起来您真正想要的是模板中每个 resultdict() 类似对象。为此,请避免将字典转储为 JSON。

    所以而不是:

    # WRONG:
    json_docs = [json.dumps(doc, default=json_util.default) for doc in results]       
    return render(request, 'db.html', {'results': json_docs[0:3]})
    # /WRONG
    

    ...直接将结果传入即可:

     results = settings.vali_collection.find({'index': []  })
     results = list(results)  # This may or may not be necessary, depending on what mongo client you're using
     return render(request, 'db.html', {'results' : results[:3])
    

    然后在您的模板中,当您遍历results 时,每个result 应该是一个类似字典的对象,您可以使用result.nameresult.items

    顺便说一句,您代码中的 result.items.name 引用对我来说有点奇怪(就像它会返回错误一样),但我很难在不知道每个 record 的情况下进行调试。

    【讨论】:

      【解决方案4】:

      像这样改变你的观点

      def index(request): 
          results = settings.vali_collection.find({'index': []  })
      
          return render(request, 'db.html', json.dumps({"results":results[0:3]}))
      

      您现在可以使用 for 循环进行渲染

      【讨论】:

      • 这不起作用 - 导致:执行查询后无法设置选项
      • @Navonod 您使用的是哪个 MongoDB 库?在 PyMongo 2.8 中这应该可以工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      • 2013-05-06
      • 2014-01-30
      • 2020-07-24
      • 1970-01-01
      • 2014-01-24
      相关资源
      最近更新 更多