Jinja2 check if a value exists in a list of dictionaries


I'm trying to check if a value exists within a dictionary list. Use flask 1.0.2. See the example below:

person_list_dict = [
        "name": "John Doe",
        "email": "[email protected]",
        "rol": "admin"
        "name": "John Smith",
        "email": "[email protected]",
        "rol": "user"

I found two ways to solve the problem, can you tell me which one is better?:

First option: jinja2 built-in template filter "map"

<pre>{% if "admin" in person_list_dict|map(attribute="rol") %}SI{% else %}NO{% endif %}</pre>
# return SI (john doe) and NO (john smith)

Second option: Flask template filter

Code flask:

def is_any(search="", list_dict=None, dict_key=""):
    if any(search in element[dict_key] for element in list_dict):
        return True
    return False

template code:

<pre>{% if "admin"|is_in_list_dict(person_list_dict, "rol") %} SI {% else %} NO {% endif %}</pre>
# return SI (john doe) and NO (john smith)

Thanks: -).

asked by mrroot5 07.09.2018 в 18:18

1 answer


Although it could be considered a matter of opinion, I think there are objective reasons to prefer the first approach. They would be the following:

  • Less code . When using jinja2 pre-existing filters, you do not need to add extra code in your Flask application. Less things to maintain and test.

  • More readable code . Although the map(attribute="rol") share requires knowing exactly what this function does in jinja2, it is not difficult to imagine what it will be. Once it is understood that all the "role" fields have been extracted from the list of dictionaries, it is obvious that it is enough to search if the string "admin" is among them. In return, the Flask version requires understanding what a decorator template_filter is, understanding that the list comprehension that appears in the function produces a list of booleans, and knowing the function any() . Also, once that filter is created in Flask, its use within the template is also anti-intuitive, since it is not really being used to filter a list (that is, select elements of it), but rather as a condition for the if.

  • Efficiency . Even without knowing how Jinja2 actually implements the map filter, we can assume that in the background it will be doing a list comprehension that will result in the list of strings found in the "role" field. The time required to create that list will be proportional to the number of elements in it. Once you have it, the operator cadena in lista will translate to the same operator in in Python, which is very efficient. The second version also needs to go through the list of complete dictionaries, to create a list of booleans, and then any() needs to check if there is any True (which is also very efficient, since it does not review the entire list and stop at the first True you find). Even so, the second version requires more operations when creating the Boolean list, since for each element of the original list it must compare its "role" with the one sought, and this it does for all the elements of the list (when it could have been stopped when finding the first one).

    It may seem that the difference would be negligible, but I have made some measurements and, for a list with only two elements, the first option takes 631ns and the second 833ns. Differences of nanoseconds are obviously irrelevant, but if the list were much longer they could be already important, since the second option takes 25% longer than the first.

    Not only is the processing time of the second option slightly longer, but it also adds an extra level of indirection in its execution, since the renderer of the Jinja template must invoke the python function which acts as a filter. However, the invocation is done only once and the time consumed here does not depend on the size of the list.

  • Robustness . If you try to look at a field that does not exist in dictionaries (for example, you change "rol" to "role" , the first option will still work, and will result in <pre>NO</pre> , which is reasonable.) The second option will produce an exception in the python function when trying to access element[dict_key] .

  • answered by 09.09.2018 / 13:35