Jinja 2 - 忽略破折号但仍在处理字段?
Jinja 2 - ignoring dashes but still processing field?
下午好,
我有以下 Jinja 字段:
{{ DEVICE_RTR-02:LOOPBACK_SUBNET }}
当此文件名贯穿渲染时
expected token 'end of print statement', got ':'
所以我将 : 换成了 ++ 然后我得到了
'DEVICE_RTR' is undefined
在我看来,这可能是将破折号作为一个函数?
我尝试按照下面的方式转义它,只是忽略了整个字段
{{ 'DEVICE_RTR-02++LOOPBACK_SUBNET' }}
我需要使用我在函数中拆分的分隔符 char 来获取正确的数据。 - 是数据的命名方式。
有没有办法转义所有字符但处理其中的数据?或者有人知道我可以交换什么值来完成这项工作吗?
后台函数在下面,应该可以了解我在做什么:
field_names = re.findall(r'(?s)(?<={{)(.*?)(?=}})', template.config, flags=re.S)
for i, field in enumerate(field_names):
data = field
data = data.strip()
data = data.lower()
if '|' in data:
data = data.split('|')[0]
field_names[i] = data
field_names = list(set(field_names))
template_data = {}
for name in field_names:
# reset the device_data incase it was altered with the alt name
device_data = Device.objects.get(id=device_id)
if '++' in name:
alt_data = name.split('++')[0]
if alt_data.startswith('device_'):
alt_data = alt_data.split('_')
device_data = Device.objects.get(site_id=device_data.site_id,hostname__icontains=alt_data[1])
alt_field_data = get_field_data(name.split('++')[1])
alt_field_data[name.upper()] = alt_field_data.pop(name.split('++')[1].upper())
template_data = {**template_data, **alt_field_data}
else:
template_data = {**template_data, **get_field_data(name.split('++')[1])}
else:
template_data = {**template_data, **get_field_data(name)}
谢谢
处理这些字段是因为您用来匹配它们的正则表达式是 (.*?)
,它匹配 任何东西。但是,Jinja2 docs 表示使用此正则表达式匹配标识符:
[a-zA-Z_][a-zA-Z0-9_]*
所以我猜你唯一的选择是使用下划线作为 "control character"。一种可能的解决方案如下。
模板生成时
在生成 Jinja2 模板字段 时,使用:
- double 下划线 (
__
) 代替破折号 (-
);
- 三重下划线(
___
)作为分隔符,而不是++
;
- 一个下划线作为设备名称分隔符(就像你已经做的那样)。
正在解析模板
您可以替换上述 Python 代码中的 for 循环,例如:
for name in field_names:
# reset the device_data incase it was altered with the alt name
device_data = Device.objects.get(id=device_id)
if '___' in name: # look for separator
alt_data = name.split('___')[0]
if alt_data.startswith('device_'):
hname = alt_data[7:] # this line has changed
device_data = Device.objects.get(site_id=device_data.site_id,hostname__icontains=hname)
alt_field_data = get_field_data(name.split('___')[1])
alt_field_data[name.upper()] = alt_field_data.pop(name.split('___')[1].upper())
template_data = {**template_data, **alt_field_data}
else:
template_data = {**template_data, **get_field_data(name.split('___')[1])}
else:
template_data = {**template_data, **get_field_data(name)}
下午好,
我有以下 Jinja 字段:
{{ DEVICE_RTR-02:LOOPBACK_SUBNET }}
当此文件名贯穿渲染时
expected token 'end of print statement', got ':'
所以我将 : 换成了 ++ 然后我得到了
'DEVICE_RTR' is undefined
在我看来,这可能是将破折号作为一个函数?
我尝试按照下面的方式转义它,只是忽略了整个字段
{{ 'DEVICE_RTR-02++LOOPBACK_SUBNET' }}
我需要使用我在函数中拆分的分隔符 char 来获取正确的数据。 - 是数据的命名方式。
有没有办法转义所有字符但处理其中的数据?或者有人知道我可以交换什么值来完成这项工作吗?
后台函数在下面,应该可以了解我在做什么:
field_names = re.findall(r'(?s)(?<={{)(.*?)(?=}})', template.config, flags=re.S)
for i, field in enumerate(field_names):
data = field
data = data.strip()
data = data.lower()
if '|' in data:
data = data.split('|')[0]
field_names[i] = data
field_names = list(set(field_names))
template_data = {}
for name in field_names:
# reset the device_data incase it was altered with the alt name
device_data = Device.objects.get(id=device_id)
if '++' in name:
alt_data = name.split('++')[0]
if alt_data.startswith('device_'):
alt_data = alt_data.split('_')
device_data = Device.objects.get(site_id=device_data.site_id,hostname__icontains=alt_data[1])
alt_field_data = get_field_data(name.split('++')[1])
alt_field_data[name.upper()] = alt_field_data.pop(name.split('++')[1].upper())
template_data = {**template_data, **alt_field_data}
else:
template_data = {**template_data, **get_field_data(name.split('++')[1])}
else:
template_data = {**template_data, **get_field_data(name)}
谢谢
处理这些字段是因为您用来匹配它们的正则表达式是 (.*?)
,它匹配 任何东西。但是,Jinja2 docs 表示使用此正则表达式匹配标识符:
[a-zA-Z_][a-zA-Z0-9_]*
所以我猜你唯一的选择是使用下划线作为 "control character"。一种可能的解决方案如下。
模板生成时
在生成 Jinja2 模板字段 时,使用:
- double 下划线 (
__
) 代替破折号 (-
); - 三重下划线(
___
)作为分隔符,而不是++
; - 一个下划线作为设备名称分隔符(就像你已经做的那样)。
正在解析模板
您可以替换上述 Python 代码中的 for 循环,例如:
for name in field_names:
# reset the device_data incase it was altered with the alt name
device_data = Device.objects.get(id=device_id)
if '___' in name: # look for separator
alt_data = name.split('___')[0]
if alt_data.startswith('device_'):
hname = alt_data[7:] # this line has changed
device_data = Device.objects.get(site_id=device_data.site_id,hostname__icontains=hname)
alt_field_data = get_field_data(name.split('___')[1])
alt_field_data[name.upper()] = alt_field_data.pop(name.split('___')[1].upper())
template_data = {**template_data, **alt_field_data}
else:
template_data = {**template_data, **get_field_data(name.split('___')[1])}
else:
template_data = {**template_data, **get_field_data(name)}