如何在Django的HTML模板中访问JSONField的嵌套字段
解决模板中无法访问字典数字键嵌套值的问题
看起来你遇到的核心问题是模板引擎对字典的字符串数字键处理逻辑导致的——当你尝试用{{ user.data.2020.amount }}这种点语法访问时,模板会把2020当成整数索引去尝试访问序列(比如列表),但你的data是字典,所以无法匹配到对应的键,自然取不到值。
下面给你几个可行的解决方案:
方案1:遍历字典键值对(适合动态年份场景)
如果你的年份不固定,或者想自动适配所有年份列,可以直接遍历user.data的键值对:
<div class="media-body"> <table> <tr> <th>Name</th> <!-- 先动态生成年份表头 --> {% for year in users.0.data.keys %} <th>{{ year }}</th> {% endfor %} </tr> {% for user in users%} <tr> <td>{{ user.name }}</td> <!-- 遍历每个用户的年份数据 --> {% for year, payment_info in user.data.items %} <td>{{ payment_info.amount }}</td> {% endfor %} </tr> {% endfor %} </table> </div>
注意:Python 3.7+的字典是有序的,所以遍历顺序会和你存储的一致;如果是更低版本,建议在视图层先把年份排序后再传给模板。
方案2:自定义模板过滤器(适合固定年份场景)
如果你的年份是固定的(比如只需要2020和2021),可以自定义一个模板过滤器来安全地获取字典的键值:
步骤1:创建自定义过滤器
在你的应用下创建templatetags目录,里面新建两个文件:
__init__.py(空文件即可)custom_filters.py,内容如下:
from django import template register = template.Library() @register.filter(name='get_item') def get_item(dictionary, key): # 用get方法避免键不存在时报错 return dictionary.get(key, {})
步骤2:在模板中使用过滤器
在模板开头加载过滤器,然后就可以用它来获取指定键的值:
{% load custom_filters %} <div class="media-body"> <table> <tr> <th>Name</th> <th>2020</th> <th>2021</th> </tr> {% for user in users%} <tr> <td>{{ user.name }}</td> <td>{{ user.data|get_item:"2020"|get_item:"amount" }}</td> <td>{{ user.data|get_item:"2021"|get_item:"amount" }}</td> </tr> {% endfor %} </table> </div>
方案3:在视图层预处理数据(更灵活)
如果你不想修改模板或写过滤器,也可以在视图里把嵌套数据提前解析好,比如给每个user对象添加对应年份的金额属性:
# 假设你的视图逻辑如下 def user_list(request): users = User.objects.all() for user in users: # 从data字典中提取金额,默认0避免空值 user.year_2020_amount = user.data.get("2020", {}).get("amount", 0) user.year_2021_amount = user.data.get("2021", {}).get("amount", 0) return render(request, 'user_list.html', {'users': users})
然后在模板里直接访问:
<div class="media-body"> <table> <tr> <th>Name</th> <th>2020</th> <th>2021</th> </tr> {% for user in users%} <tr> <td>{{ user.name }}</td> <td>{{ user.year_2020_amount }}</td> <td>{{ user.year_2021_amount }}</td> </tr> {% endfor %} </table> </div>
这三个方案各有优缺点,你可以根据自己的业务场景选择最合适的~
内容的提问来源于stack exchange,提问作者CutePoison
相关产品推荐
相关产品推荐

