AlexW
AlexW

Reputation: 2587

Jinja 2 - ignoring dashes but still processing field?

Good afternoon,

I have the below Jinja field:

{{ DEVICE_RTR-02:LOOPBACK_SUBNET }}

When this filename runs through the render

expected token 'end of print statement', got ':'

so I swapped the : for a ++ instead and then I get

'DEVICE_RTR' is undefined

Which to me looks like its taking the dash symbol as a function possibly?

I tried escaping it as per the below, that just ignores the whole field

{{ 'DEVICE_RTR-02++LOOPBACK_SUBNET' }}

I need to use a separator char which I split against in my function to get the right data. and the - is how the data is named.

is there a way to escape all chars but process the data in it? or does anyone know what values I can swap to make this work?

background function is below, which should give an idea of what im doing:

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)} 

Thanks

Upvotes: 0

Views: 1194

Answers (1)

Paolo Stefan
Paolo Stefan

Reputation: 10263

The fields are processed because the regex you use to match them is (.*?) which matches anything. But, the Jinja2 docs say that identifiers are matched using this regex:

[a-zA-Z_][a-zA-Z0-9_]*

So I guess your only option is use the underscore as "control character". One possible solution could be the following.

When the template is generated

At the moment of generating the Jinja2 template fields, use:

  • double underscores (__) in place of the dash (-);
  • triple underscores (___) as a separator, instead of ++;
  • one underscore as device name separator (like you already do).

Parsing the template

You can replace the for loop in the above Python code like e.g.:

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)} 

Upvotes: 1

Related Questions