【问题标题】:How to re-render django template code on AJAX call如何在 AJAX 调用上重新渲染 django 模板代码
【发布时间】:2016-09-27 14:43:40
【问题描述】:

我有一个视图,它将分页对象(在查询集上)发送到模板,我进一步在模板中将其呈现为表格。我要做的是单击模板上分页栏上的页码,它应该进行 ajax 调用以获取该页码的分页输出并用它动态更新表的内容。

查看:

def accounts(request):
    #Including only necessary part
    accounts_list = Accounts.objects.all()
    paginator = Paginator(accounts_list, 25)
    page = request.GET.get('page')
    try:
        accounts = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        accounts = paginator.page(1)
    except EmptyPage:
        # If page is out of range, deliver last page of results.
        accounts = paginator.page(paginator.num_pages)

    context['accounts'] = accounts
    return render(request, template, context)

模板将其加载为:

{% if accounts %}
<table id="acc">
    <tr>
        <th>Field 1</th>
        ...
        <th>Field N</th>
    </tr>
    {% for item in accounts %}
    <tr> 
        <td>{{ item.field1 }}</td>
        ...<!-- Some complex logic with template tags too in here -->
        <td>{{ item.fieldN }}</td>
    </tr>
    {% endfor %}
</table>
{% endif %}

现在对于分页栏,我使用Bootpag's library,我可以将内容渲染为:

$('.pagination_top').bootpag({
   /*bootpag logic here */
}).on("page", function(event, num){
    //$.ajax loading here where I can update the table div with new output 
    //or make the table div "template code" reload without reloading page
}

抱歉,我没有展示我在 ajax 部分尝试过的大部分内容,因为我对如何使模板重新渲染返回新帐户而不重新加载页面完全一无所知。

我能想到的唯一肮脏的解决方案是在视图中生成我的整个 html,然后使用返回的新 html ajax 更新表格 div 的 html?

在不重新加载页面的情况下使用模板呈现逻辑重新加载表格 div 的简单方法是什么?这可以通过使表格部分成为单独的模板并包含/扩展模板来实现吗?

请注意我不能使用模板上的所有数据,然后使用一些jquery/js libaray的分页逻辑的方法,因为完整的数据比较大。

【问题讨论】:

    标签: jquery ajax django django-pagination


    【解决方案1】:

    我解决了以下问题:

    将表格部分作为模板table.html分隔为:

    app/table.html:

    {% if accounts %}
    <table id="acc">
        <tr>
            <th>Field 1</th>
            ...
            <th>Field N</th>
        </tr>
        {% for item in accounts %}
        <tr> 
            <td>{{ item.field1 }}</td>
            ...<!-- Some complex logic with template tags too in here -->
            <td>{{ item.fieldN }}</td>
        </tr>
        {% endfor %}
    </table>
    {% endif %}
    

    在主模板 main.html 中将其称为包含模板:

    app/main.html:

    <div class="table-responsive">
        {% include 'app/table.html' %}
    </div>
    

    现在,在我看来,我添加了一行,如果请求是 ajax 请求,则仅呈现给 table.html

    if request.is_ajax():
            return render(request, 'app/table.html', context)
    #else
    return render(request, 'app/main.html', context)
    

    在分页时重新加载表格:

    $('.pagination_top').bootpag({
       /*bootpag logic here */
    }).on("page", function(event, num){
        $(".table-responsive").html('').load(
            "{% url 'app:accounts' %}?page=" + num
        );
    });
    

    【讨论】:

    • 你的 js 脚本还在重新加载页面,页面 url 每次点击都会改变?
    • 不,它不会重新加载页面。
    【解决方案2】:

    如果你想依赖 django 模板,你应该重新加载页面并在请求中发送分页信息。这是通常所做的(例如在 django-admin 中)。它需要重新加载页面,但这就是 django 模板的用途。

    否则我会将整个渲染委托给客户端,并在 django 中只提供一个 JSON 视图。这样 django 将提供一个模板,其中包含一些标记以及您最喜欢的 js 库,它负责进行 AJAX 调用并直接自己呈现数据。

    更新:

    如果你真的需要这样做,你提到的方法是可能的。没有什么能阻止您渲染模板的一部分,外包在单独的文件中,并将已经渲染的 HTML 发送给您的客户端。

    因此,您可以使用include template tag 将表格模板移动到单独的文件中。 对于 AJAX 调用,您应该使用第二个视图,它只呈现模板的表格部分。

    所有这一切对我来说都是一个 hacky,但它应该可以工作。

    【讨论】:

    • 这种场景下没有办法用django templatetags渲染ajax返回的数据吗?因为我的很多逻辑都依赖于那些模板标签
    • 如果我必须在视图本身中生成整个 html,需要分离模板吗?
    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 2020-11-17
    • 2015-08-09
    相关资源
    最近更新 更多