如何在 AJAX 调用时重新呈现 Django 模板代码
How to re-render django template code on AJAX call
我有一个将分页对象(在查询集上)发送到模板的视图,我进一步在模板中将其呈现为 table。我想做的是单击模板上分页栏上的页码,它应该进行 ajax 调用以获取该页码的分页输出并动态更新 table 的内容。
查看:
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,然后用新的 [=更新 table div 的 html 36=] ajax 返回?
在不重新加载页面的情况下使用模板呈现逻辑重新加载 table div 的简单方法是什么?这可以通过使 table 部分成为单独的模板和 including/extending 模板来实现吗?
请注意我不能使用在模板上获取所有数据然后使用某些jquery/js libaray的分页逻辑的方法,因为完整的数据相对非常多大。
如果您想依赖 Django 模板,您应该重新加载页面并在请求中发送分页信息。这是通常所做的(例如在 django-admin 中)。它需要重新加载页面,但这正是 django 模板的用途。
否则我会将整个渲染委托给客户端,并只在 django 中提供一个 JSON 视图。这样 django 将提供一个模板,其中包含一些标记和您最喜欢的 js 库,负责进行 AJAX 调用并直接在其自身上呈现数据。
更新:
如果你真的需要这样做,你说的方法是可以的。没有什么能阻止您渲染模板的一部分,在单独的文件中外包并将已经渲染的 HTML 发送给您的客户。
因此您可以利用 include template tag 将 table 模板移动到一个单独的文件中。
对于 AJAX 调用,您应该使用第二个视图,它只呈现模板的 table 部分。
所有这些对我来说感觉很麻烦,但它应该有效。
我解决问题如下:
将 table 部分作为模板 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)
重新加载 table 分页为:
$('.pagination_top').bootpag({
/*bootpag logic here */
}).on("page", function(event, num){
$(".table-responsive").html('').load(
"{% url 'app:accounts' %}?page=" + num
);
});
我有一个将分页对象(在查询集上)发送到模板的视图,我进一步在模板中将其呈现为 table。我想做的是单击模板上分页栏上的页码,它应该进行 ajax 调用以获取该页码的分页输出并动态更新 table 的内容。
查看:
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,然后用新的 [=更新 table div 的 html 36=] ajax 返回?
在不重新加载页面的情况下使用模板呈现逻辑重新加载 table div 的简单方法是什么?这可以通过使 table 部分成为单独的模板和 including/extending 模板来实现吗?
请注意我不能使用在模板上获取所有数据然后使用某些jquery/js libaray的分页逻辑的方法,因为完整的数据相对非常多大。
如果您想依赖 Django 模板,您应该重新加载页面并在请求中发送分页信息。这是通常所做的(例如在 django-admin 中)。它需要重新加载页面,但这正是 django 模板的用途。
否则我会将整个渲染委托给客户端,并只在 django 中提供一个 JSON 视图。这样 django 将提供一个模板,其中包含一些标记和您最喜欢的 js 库,负责进行 AJAX 调用并直接在其自身上呈现数据。
更新:
如果你真的需要这样做,你说的方法是可以的。没有什么能阻止您渲染模板的一部分,在单独的文件中外包并将已经渲染的 HTML 发送给您的客户。
因此您可以利用 include template tag 将 table 模板移动到一个单独的文件中。 对于 AJAX 调用,您应该使用第二个视图,它只呈现模板的 table 部分。
所有这些对我来说感觉很麻烦,但它应该有效。
我解决问题如下:
将 table 部分作为模板 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)
重新加载 table 分页为:
$('.pagination_top').bootpag({
/*bootpag logic here */
}).on("page", function(event, num){
$(".table-responsive").html('').load(
"{% url 'app:accounts' %}?page=" + num
);
});