如何在Jinja模板中转换datetime以更新SQL表?
Jinja模板中处理datetime适配SQL更新的方法
问题根源
Jinja没有内置的datetime类型测试器,所以你写的val is datetime会报错。另外需要把带时区后缀的datetime字符串(如2023-02-13 20:56:13.112000+00:00)转换成不带时区的格式。
具体解决方案
1. 替换datetime类型判断
把模板里的{% elif val is datetime %}替换成直接判断类型名称的写法,适配不同环境下的datetime类型:
{% elif val.__class__.__name__ in ('datetime', 'datetime.datetime') %}
2. 格式化datetime值
有两种可靠的格式化方式:
- 方式一:字符串切片(兼容所有datetime对象,包括带时区的)
直接对datetime的字符串形式切片,去掉时区后缀,写法简单通用:{{col}} = '{{str(val).split('+')[0]}}' - 方式二:用strftime指定格式(适合原生无时区datetime对象)
精确指定输出格式,保留微秒信息:{{col}} = '{{val.strftime('%Y-%m-%d %H:%M:%S.%f')}}'
3. 完整修改后的模板
UPDATE {{database_name}}.{{table_name}} SET {% for col, val in zip(column_list, value_list) %} {% if val is string %} {{col}} = '{{val}}' {% elif val.__class__.__name__ in ('datetime', 'datetime.datetime') %} {{col}} = '{{str(val).split('+')[0]}}' {% else %} {{col}} = {{val}} {% endif %} {% if not loop.last %},{% endif %} {% endfor %} WHERE 1= 1 {% for key,val in filters.items() %} {% if val is sequence and val is not string and val is not mapping %} AND {{key}} in ({% for i in val %} {% if i.__class__.__name__ in ('datetime', 'datetime.datetime') %} '{{str(i).split('+')[0]}}' {% elif i is string %} '{{i}}' {% else %} {{i}} {% endif %} {% if not loop.last %},{% endif %} {% endfor %}) {% elif val is string %} AND {{key}} = '{{val}}' {% elif val is number %} AND {{key}} = {{val}} {% elif val is boolean %} AND {{key}} = {{val}} {% elif val.__class__.__name__ in ('datetime', 'datetime.datetime') %} AND {{key}} = '{{str(val).split('+')[0]}}' {% else %} AND {{key}} = '{{ val }}' {% endif %} {% endfor %}
额外优化方案
如果你的项目有权限修改后端渲染代码,可以给Jinja注册自定义的datetime测试器,让模板写法更简洁:
from jinja2 import Environment from datetime import datetime def is_datetime(value): return isinstance(value, datetime) # 初始化Jinja环境时注册测试器 env = Environment() env.tests['datetime'] = is_datetime
注册后模板里就能直接用{% elif val is datetime %}的判断逻辑。
内容的提问来源于stack exchange,提问作者Masterstack8080
相关产品推荐
相关产品推荐

