Bob's Blog

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

返回上页首页

用Django做一个简单的记账网站(九)自定义模板过滤器



已经能提交表单数据并保存账单了,于是需要在打开页面时请求账单历史记录的数据,并显示在页面上。

期望的是把账单按每一天来整合,并能显示汇总的收支信息,于是返回的数据就会有每日账单和每日收支,类似如下:

# 每日账单
{'2021-01-20': [<HistoryRecord: HistoryRecord object (16)>], '2021-01-19': [<HistoryRecord: HistoryRecord object (15)>], '2021-01-18': [<HistoryRecord: HistoryRecord object (14)>, <HistoryRecord: HistoryRecord object (13)>]}
# 每日收支
{'2021-01-20': {'income': 0, 'expense': Decimal('30.00')}, '2021-01-19': {'income': Decimal('450.12'), 'expense': 0}, '2021-01-18': {'income': 0, 'expense': Decimal('3018.00')}}

对于账单来说,可以通过for循环来显示在页面上,但收支每天只有一个,需要在循环日期时使用,在循环账单时不使用。

html的template就可以是如下:

{% for day, records in current_month_records.items %}
<div class="card" style="margin: 0px 20px 10px 20px;">
    <div class="card-header" style="font-size: 80%;">
        <div style="float: left;">{{ day }}</div>
        <div style="float: right;">
            收入: | 支出:
        </div>
    </div>
    <ul class="list-group list-group-flush">
        {% for hr in records %}
        <li class="list-group-item">
            {% if hr.sub_category %}
            <div style="float: left;">{{ hr.category }} - {{ hr.sub_category }}</div>
            {% else %}
            <div style="float: left;">{{ hr.category }}</div>
            {% endif %}
            {% if hr.category.category_type == 'Income' %}
            <div style="float: right; color: green;">{{ hr.amount }}</div>
            {% else %}
            <div style="float: right; color: red;">{{ hr.amount }}</div>
            {% endif %}
            <br>
            {% if hr.comment %}
            <div style="float: left; font-size: 80%; color: gray;">{{ hr.comment }}</div>
            {% endif %}
            <div style="float: right; font-size: 80%; color: gray;">{{ hr.account }}</div>
        </li>
        {% endfor %}
    </ul>
</div>
{% endfor %}

{% for day, records in current_month_records.items %}这代表着循环每日账单的字典元素,并取回日期(key)和当日账单记录(value),当日账单记录会再做一次for循环。

于是问题来了,在收入支出那里就不能再做一次循环,而是需要通过dict[key]的方式来取对应的值,获得当日的收支状况。

很遗憾,django template并不默认支持这样的取值。(其实django template可以支持类似加法之类的操作,比如{{ income | add: expense }},但是没有直接可用的取字典值的方法。)

于是我们可以添加一个自定义的template tags,有的叫模板标签,有的也叫模板过滤器。

在accounting/views.py同级目录下创建一个python package,取名为templatetags,在其中默认生成了一个__init__.py,然后自己创建一个脚本,假设取名为filter_dict.py,在其中加入代码:

from django import template

register = template.Library()

@register.filter('get_dict_value')
def get_dict_value(d, key):
    return d[key]

这段代码意味着我可以在template里调用get_dict_value这个方法来为字典取值了。

于是在刚才的html template片段中把收支的部分改为如下:

{% load filter_dict %}
<div style="float: right;">
    收入:{{ day_income_expense|get_dict_value:day|get_dict_value:'income' }} | 支出:{{ day_income_expense|get_dict_value:day|get_dict_value:'expense' }}
</div>

这样便能完成自定义模板过滤器,并协助自己筛选字典值了。

然后页面就能完成为下面的图片的样子,能显示每日的账单整合信息,并显示每日的收支汇总信息。

下一篇:  Echarts在bootstrap切换tab时无法正常显示的解决办法
上一篇:  用Django做一个简单的记账网站(八)提交表单

共有5条评论

添加评论

Khakikiddo
2024年3月7日 17:22
请问博主,current_month_records该如何定义呢
Khakikiddo
2024年3月7日 17:22
请问博主,current_month_records该如何定义呢
yp
2022年5月3日 23:55
你好!我后台数据库有更新,但是为什么页面上无法显示账单的列表,会显示'NoneType' object has no attribute 'category_type'
Bo
2021年5月9日 19:47
@hp2 bobjiang4321@gmail.com
hp2
2021年5月9日 19:15
能留个联系方式吗