简体   繁体   中英

Comparing Symmetric Dictionaries in Jinja2 template

I am passing two symmetric dictionaries to a jinja2 template for rendering. These two dictionaries are installed and required. I want to compare the values in installed and required to ensure they are the same version. The version numbers are stored as strings. If the versions are not equal, I want to highlight that row in my table.

The values print out correctly, but the comparison always fails.

<table border="1">
  <tr>
    <td>Package</td>
    <td>Version Required</td>
    <td>Version Installed</td>
  </tr>

{% for key, value in required.items() %}
{% if installed[key] == required[key] %} 
    <tr>
    <td>{{key}}</td>
    <td>{{value}}</td>
    <td>{{installed[key]}}</td>
    </tr>
{% else %}
    <tr bgcolor="#ff0000">
    <td>{{key}}</td>
    <td>{{value}}</td>
    <td>{{installed[key]}}</td>
    </tr>
{% endif %} 
{% endfor %}
</table>

It is better to keep logic out of jinja2 template as much as possible and create well usable data in Python code:

render.py

Instead of two dictionaries, we may pass in a list with tuples (package_name, req_ver, installed_ver)

from jinja2 import Template

with open("table.jinja2") as f:
    templ = Template(f.read())
required = {"boto": "1.1.1", "plac": "2.2.3", "pyyaml": "3.3.3", "jinja2": "4.4.4"}
installed = {"boto": "1.1.1", "plac": "2.2.2", "pyyaml": "3.3.3", "jinja2": "4.4.4"}

packages = [(key, installed[key], required[key]) for key in sorted(installed)]

print templ.render(packages=packages)

table.jinja2

In the template, we may modify just the bgcolor , either by hardcoded color code, or even better by changing a style (not shown here).

I also used white space controll - inside the control structures.

<table border="1">
    <tr><td>Package</td> <td>Version Required</td><td>Version Installed</td></tr>
{%- for name, ver_required, ver_installed in packages %}
    <tr{% if ver_required != ver_installed %} bgcolor="#ff0000" {% endif %}>
        <td>{{name}}</td> <td>{{ver_required}}</td> <td>{{ver_installed}}</td>
    </tr>
{%- endfor %}
</table>

Run it:

$ python render.py >tabl.html

And preview the table in web browser.

<table border="1">
    <tr><td>Package</td> <td>Version Required</td><td>Version Installed</td></tr>
    <tr>
        <td>boto</td> <td>1.1.1</td> <td>1.1.1</td>
    </tr>
    <tr>
        <td>jinja2</td> <td>4.4.4</td> <td>4.4.4</td>
    </tr>
    <tr bgcolor="#ff0000" >
        <td>plac</td> <td>2.2.2</td> <td>2.2.3</td>
    </tr>
    <tr>
        <td>pyyaml</td> <td>3.3.3</td> <td>3.3.3</td>
    </tr>
</table>

Jan's answer is excellent, but I also found the specific issue I was having. The problem was one of the strings had a special character on the end, while the other did not.

I was able to fix the code by adding .rstrip("\\r\\n") to the end of each string.

You can tell if you are having a similar issue by putting each string into len() and outputting their sizes. If they are not equal, then there is a special character.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM