Skip to main content
 首页 » 编程设计

python之Django的模板语言不能安全的处理dict

2025年05月04日16Leo_wl

在django的模板语言中,如果一个变量名为a.x,那么django会按照这个顺序尝试获取正确的值:

  1. a['x'], 字典查找
  2. a.x 或a.x(),属性或方法查找
  3. a[x],列表索引

结果是:任何支持 var['str'] 的变量都变成了定时炸弹。假设 a 是一个 dict,具有值为 'hello world' 的键 'items',那么 a.items 将导致 'hello world',而不是 ditc.items()。这是代码:

from django.template import Engine, Context 
template = """ 
{% for k, v in a.items %} 
{{ k }} = {{ v }} 
{% endfor %} 
""" 
 
e = Engine() 
t = e.from_string(template) 
a = {'items': 'hello world'} 
print(t.render(Context({'a': a}))) 

虽然我期望 items = hello world 作为输出,但实际输出是:

h =  
 
e =  
 
l =  
... 

对于字典变量,如果它有一个与字典方法同名的键,那么你将永远无法在模板中调用该方法。它变成了一颗定时炸弹,因为您永远不知道将来是否会在字典变量中添加一个名为“items”的键。

这种风险不仅存在于 dict,还存在于任何接受 var['key'] 的类型。

所以我的问题是,为什么订单是这样设计的,如何保证安全。

请您参考如下方法:

有一个简单的解决方法(除了为您的 key 使用更好的名称之外):

from django.template import Engine, Context 
 
template = """ 
{% for k, v in items_func %} 
{{ k }} = {{ v }} 
{% endfor %} 
""" 
 
e = Engine() 
t = e.from_string(template) 
a = {'items': 'hello world'} 
print(t.render(Context({'a': a, 'items_func': a.items}))) 
>> items = hello world