用Django做一个简单的记账网站(六)处理Ajax请求
经过前一篇的操作,已经令界面有了美化。但是由于数据是默认展示所有,于是需要修改为根据用户的选择来决定加载部分数据内容。
比如选择了大类别,会显示对应的小类别。
Ajax是与服务器进行异步交互,根据用户行为来请求对应的接口获取数据并改变页面。无需刷新整个页面。无需在打开页面时就加载。
当加载了收支类型后,我们想默认选中'支出',可以在html中添加script:
<script>
$(function () {
var init_ie_type = 'expense'
$("#ie-type-list").find(`option[value=${init_ie_type}]`).attr("selected", true);
})
</script>
这样默认就会选中'支出'类型。
但是相对的大类别和小类别也需要随着收支类型的变化而变化才对。
首先在views.py中新建获取类别的方法:
def retrieve_category(request):
ie_type = request.POST.get('ie_type')
categories = Category.objects.filter(category_type=ie_type)
category_list = []
for c in categories:
category_list.append(c.name)
return JsonResponse({"categories": category_list})
更新urls.py,添加能指向该方法的url:
urlpatterns = [
path('', views.index, name='index'),
path('retrieve_category/', views.retrieve_category, name='retrieve_category'),
]
此时便可以加上ajax来异步post收支类型,并获取对应的类别更新在select list中。
<script>
$(function () {
var init_ie_type = 'expense'
var init_category_type = '餐饮'
$("#ie-type-list").find(`option[value=${init_ie_type}]`).attr("selected", true);
$.ajax({
type: "POST",
data: {ie_type: init_ie_type},
url: "{% url 'retrieve_category' %}",
cache: false,
dataType: "json",
success: function (result) {
var options = "";
result["categories"].forEach(function(val,index,arr) {
new_option = '<option value="' + val + '">' + val + '</option>';
options += new_option;
});
var category_list = document.getElementById("category-list");
category_list.innerHTML = options;
$("#category-list").find(`option[value=${init_category_type}]`).attr("selected", true);
}
});
})
</script>
不过你会遇到403的错误,此时需要带上csrf_token,在刚才的js之前添加如下内容:
<script>$.ajaxSetup({headers: {"X-CSRFToken": '{{ csrf_token }}'}});</script>
此时在打开页面时,便可以更新默认的选中项,并更新了对应的类别信息。当然,这部分在index的方法中直接返回也是可以的。
当用户在选择其他收支类型或者类别时,此时便必须通过ajax来异步请求数据了。比如用户从'支出'切换到'收入',那么对应的大小类别时需要被更新的,不能在选中了'收入'仍然显示购物餐饮等类别。于是需要在选中项发生变化时触发ajax请求:
<script>
$(function () {
$('#ie-type-list').change(function(){
var current_ie_type = $(this).children('option:selected').val();
$.ajax({
type: "POST",
data: {ie_type: current_ie_type},
url: "{% url 'retrieve_category' %}",
cache: false,
dataType: "json",
success: function (result) {
var options = "";
result["categories"].forEach(function(val,index,arr) {
if (index == 0) {
new_option = '<option value="' + val + '" selected="selected">' + val + '</option>';
options += new_option;
}
else {
new_option = '<option value="' + val + '">' + val + '</option>';
options += new_option;
}
});
var category_list = document.getElementById("category-list");
category_list.innerHTML = options;
}
});
});
})
</script>
这样无论用户怎么切换类型,都能展示正确的类别供用户选择了。
接下来写如何提交保存记账数据。
共有11条评论
添加评论
Bo
2022年12月2日 10:11@cjy script加在body的后面,和body平级就可以
cjy
2022年12月1日 22:19@Bo 这里的script具体放在哪里呀?我分别放在body的最前面和最后面都没有用。
Bo
2021年3月2日 17:42@Yako 我这里无法复现这个问题,你看看js里是不是有默认值但是不存在你的类别数据中
Yako
2021年3月2日 17:39@Bo,简单说就是刷新页面后,几个下拉输入框的默认值不太对,和设置的不同,但是重新在下拉表里选一次就好了,对应关系也都对
Bo
2021年3月1日 17:51@Yako 按最开始想的sub_category是绑定于category的,比如选择大类为交通,会出现小类包含地铁或公交,选择其他大类,小类也会跟着换。你说的是先是sub_category关联好了?我有点没理解到
Yako
2021年3月1日 17:43我这边下拉菜单都是要手动选择一次之后下一级菜单才会同步好,比如我sub_category已经关联好了,但是要手动选一次category才能关联到一二级菜单
q
2021年1月19日 15:52@bo 明白了,谢谢。
bo
2021年1月19日 15:47@q 这是因为没有添加sub category的ajax处理。category是根据收支类型来处理的,sub category根据category来处理即可。它和category的思路相同,代码很相似,这里就没有贴出来了,你可以试试加上这部分。
q
2021年1月19日 15:40@bo 感谢,category里的选项可以根据收入支出筛选了,但是sub category 里的选项还是会显示全部。。。。
bo
2021年1月19日 15:10@q 这里提到的<script>是放body后
q
2021年1月19日 15:06<script>是加到head里吗?到了这一步老是不成功