【问题标题】:Should I be worried about Django template inefficiencies?我应该担心 Django 模板效率低下吗?
【发布时间】:2014-01-28 14:36:14
【问题描述】:

我对 Django 比较陌生,我正在使用 1.5 版来构建 REST api。对 api 的调用期望返回 JSON(我将它与 Ember.js 前端一起使用)。

我想知道我是否不能这样做:

def listproject(request, pk_id):
  # list single project at /projects/<pk_id>
  project = Project.objects.get(pk = pk_id)
  snapshots = Snapshot.objects.filter(project = project)

  # (both are same up to here)

  return render_to_response('project.json',
    {"project":project, "snapshots":snapshots},
    mimetype="text/json")

project.json 是这个 Django 模板的位置:

{
  "id": "{{ project.pk }}",
  "name": "{{ project.name }}",
  "snapshot_ids": [ {% for snapshot in snapshots %}"{{ snapshot.pk }}"{% if not forloop.last %}, {% endif %}{% endfor %}
}

使用 Django 的时间比我长得多的人建议为此使用模板效率低下。他建议我改为:

def listproject(request, pk_id):
  # list single project at /projects/<pk_id>
  project = Project.objects.get(pk = pk_id)
  snapshots = Snapshot.objects.filter(project = project)

  # (both are same up to here)

  ret_json = []
  ret_json.append('{"id": "' + str(project.pk) + '", ')
  ret_json.append('"name": "' + project.name + '", "snapshot_ids": [')

  snapshot_json = []
  for snapshot in snapshots:
    snapshot_json.append('"' + str(snapshot.pk) + '",')
  ret_json.append(''.join(snapshot_json)[0:-1] + ']}')

  return HttpResponse(content=''.join(ret_json), mimetype="text/json")

我都测试过。它们的工作方式相同,但我的版本生成的 JSON 可读性更强。

请帮助我们结束辩论!哪个更有效(为什么)?

【问题讨论】:

  • 你为什么只问效率?这不是唯一的标准(你编写 Python,你开始的速度比必要的慢好几倍!)。易于编写和更改它呢?可理解性如何?
  • 好点!虽然这是针对生产代码的,所以它的要求更严格一些。 Daniel 和 Anentropic 的答案被证明更容易编写、更改和理解,除了是“正确的方法”之外。到处都是优点!

标签: python django json django-templates ember-data


【解决方案1】:

确实,Django 模板并不是特别有效。但是,只有当您拥有非常大的模板,这些模板本身扩展或包含许多其他模板时,这才是真正的问题,例如在复杂的内容管理系统中。对于像您这样包含少量字段的单个模板,与服务请求的总体开销相比,模板呈现微不足道。

也就是说,我对您的两种选择都感到有些困惑。为什么不通过标准 json 库生成 JSON?这是正确的做法,而不是在模板或 Python 代码中构建字符串。

ret = {'id': project.id,
       'name': project.name,
       'snapshot_ids': [snapshot.id for snapshot in snapshots]}
ret_json = json.dumps(ret)

【讨论】:

  • 'snapshot_ids': [snapshot.id for snapshot in snapshots] 我不熟悉这种语法。供参考:list comprehensions.
  • 现在看起来很明显,但我发誓不是这样!感谢您的回答丹尼尔!列表推导也可以再次用于制作项目数组版本。避免字符串破解感觉很好 =)
【解决方案2】:

这两个选项在我看来都很可怕。我宁愿尽可能避免“手写”JSON,直接从 Python 数据结构转换。

幸运的是,json 模块就是为此而设计的。

import json

def listproject(request, pk_id):
    # list single project at /projects/<pk_id>
    project = Project.objects.get(pk=pk_id)
    snapshots = Snapshot.objects.filter(project=project)
    data = {
      "id": project.pk,
      "name": project.name,
      "snapshot_ids": [snapshot.pk for snapshot in snapshots],
    }
    return HttpResponse(content=json.dumps(data), mimetype="text/json")

避免“手写”代码的原因很明显 - 避免拼写错误,代码更短更简单,json 模块可能更快。

如果您担心生成的 JSON 的“可读性”,json 模块提供了一些用于控制输出(缩进等)的选项:
http://docs.python.org/2/library/json.html

【讨论】:

    【解决方案3】:

    我通常使用这个小功能:

    import json
    from django.http import HttpResponse
    
    def json_response(ob):
        return HttpResponse(
            json.dumps(ob), mimetype="application/json")
    

    那么你可以从视图中返回结果:

    def listproject(request, pk_id):
        project = Project.objects.get(pk=pk_id)  # Use get_object_or_404 ?
        snapshots = Snapshot.objects.filter(project=project)
        return json_response({
           "id": project.pk,
           "name": project.name,
           "snapshot_ids": [snapshot.pk for snapshot in snapshots],
        })
    

    【讨论】:

      猜你喜欢
      • 2011-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      相关资源
      最近更新 更多