在Ajax调用后通过Django模板渲染JSON对象

67 投票
8 回答
41603 浏览
提问于 2025-04-15 11:41

我一直在尝试理解在 Django 中使用 Ajax 的最佳方法。通过阅读一些资料,我了解到通常的流程是:

  1. 使用某个 JavaScript 库(比如 jQuery)来构造你的 Ajax 调用,然后在 Django 中设置一个 URL 模式来捕捉这个调用,并将其传递给一个视图函数。

  2. Python 的视图函数中,获取你感兴趣的对象,并以 JSON 格式或类似格式将它们发送回客户端(可以使用内置的序列化模块,或者 simplejson)。

  3. 在 JavaScript 中定义一个回调函数,接收 JSON 数据并解析它们,以便创建需要显示的 HTML。最后,JavaScript 脚本将 HTML 放到应该放置的地方。

现在,我仍然不明白的是 Django 模板与这一切有什么关系? 显然,我们根本没有利用模板的强大功能。理想情况下,我认为将一个 JSON 对象和一个模板名称一起返回会很好,这样数据就可以被遍历,并创建一个 HTML 块。但也许我完全错了……

我找到的唯一一个朝这个方向发展的资源是 这个代码片段 (769),但我还没有尝试过。显然,在这种情况下,所有生成的 HTML 都是在服务器端创建的,然后传递给客户端。JavaScript 回调函数只需要在正确的位置显示它。

这样会导致性能问题吗?如果没有,即使不使用上面的代码片段,为什么不直接在后端使用 Python 格式化 HTML,而不是在前端呢?

非常感谢!

更新:请使用 代码片段 942,因为它是上面那个的增强版本! 我发现这种方式的继承支持效果更好……

8 个回答

7

其实你完全可以通过Ajax返回一段已经渲染好的HTML,然后把它插入到你想要的位置上。很明显,如果你想的话,可以用Django的模板来生成这段HTML。

13

这里是我如何使用同一个模板来处理传统的渲染和Ajax响应渲染的方法。

模板:

<div  id="sortable">

{% include "admin/app/model/subtemplate.html" %}
</div>

包含的模板(也叫子模板):

<div id="results_listing">
{% if results %}
    {% for c in results %}
        .....
    {% endfor %}
{% else %}

Ajax视图:

@login_required
@render_to('admin/app/model/subtemplate.html')#annoying-decorator
def ajax_view(request):
    .....

    return { 
        "results":Model.objects.all(),
    }      

当然,你可以使用render_to_response。不过我喜欢那些麻烦的装饰器 :D

25

嘿,谢谢你,vikingosegundo!

我也喜欢用装饰器 :-)。不过在这段时间里,我一直在按照我之前提到的代码片段的方法来做。唯一要注意的是,使用第942号代码片段,因为这是一个改进版的原始代码。下面是它的工作原理:

想象一下,你有一个模板(比如说,'subtemplate.html'),里面有一个可以重复使用的有用部分:

     ........
    <div id="results">          
        {% block results %}
            {% for el in items %}
                   <li>{{el|capfirst}}</li>
            {% endfor %}
        {% endblock %}      
    </div><br />
     ........

通过在你的视图文件中导入上面的代码片段,你可以轻松地引用你模板中的任何部分。一个很酷的功能是,模板之间的继承关系也会被考虑进去,所以如果你引用一个包含另一个部分的块,依此类推,一切都应该正常工作。因此,ajax视图看起来是这样的:

from django.template import loader
# downloaded from djangosnippets.com[942]
from my_project.snippets.template import render_block_to_string

def ajax_view(request):
    # some random context
    context = Context({'items': range(100)})
    # passing the template_name + block_name + context
    return_str = render_block_to_string('standard/subtemplate.html', 'results', context)
    return HttpResponse(return_str)

撰写回答