Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

用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>

这样无论用户怎么切换类型,都能展示正确的类别供用户选择了。

接下来写如何提交保存记账数据。

下一篇:  用Django做一个简单的记账网站(七)添加日期时间选择器
上一篇:  Django的Form无法保存ManyToManyField的解决办法

共有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里吗?到了这一步老是不成功