Variable
Description
The current iteration of the loop. (1 indexed)
The current iteration of the loop. (0 indexed)
The number of iterations from the end of the loop (1 indexed)
The number of iterations from the end of the loop (0 indexed)
True if first iteration.
True if last iteration.
The number of items in the sequence.
A helper function to cycle between a list of sequences. See the explanation below.
Indicates how deep in a recursive loop the rendering currently is. Starts at level 1
Indicates how deep in a recursive loop the rendering currently is. Starts at level 0
The item from the previous iteration of the loop. Undefined during the first iteration.
The item from the following iteration of the loop. Undefined during the last iteration.
True if previously called with a different value (or not called at all).
Within a for-loop, it’s possible to cycle among a list of strings/variables each time through the loop by using the special loop.cycle helper:
Since Jinja 2.1, an extra cycle helper exists that allows loop-unbound cycling. For more information, have a look at the List of Global Functions .
Unlike in Python, it’s not possible to break or continue in a loop. You can, however, filter the sequence during iteration, which allows you to skip items. The following example skips all the users which are hidden:
The advantage is that the special loop variable will count correctly; thus not counting the users not iterated over.
If no iteration took place because the sequence was empty or the filtering removed all the items from the sequence, you can render a default block by using else :
Note that, in Python, else blocks are executed whenever the corresponding loop did not break . Since Jinja loops cannot break anyway, a slightly different behavior of the else keyword was chosen.
It is also possible to use loops recursively. This is useful if you are dealing with recursive data such as sitemaps or RDFa. To use loops recursively, you basically have to add the recursive modifier to the loop definition and call the loop variable with the new iterable where you want to recurse.
The following example implements a sitemap with recursive loops:
The loop variable always refers to the closest (innermost) loop. If we have more than one level of loops, we can rebind the variable loop by writing {% set outer_loop = loop %} after the loop that we want to use recursively. Then, we can call it using {{ outer_loop(…) }}
Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope. Older versions of Jinja had a bug where in some circumstances it appeared that assignments would work. This is not supported. See Assignments for more information about how to deal with this.
If all you want to do is check whether some value has changed since the last iteration or will change in the next iteration, you can use previtem and nextitem :
If you only care whether the value changed at all, using changed is even easier:
The if statement in Jinja is comparable with the Python if statement. In the simplest form, you can use it to test if a variable is defined, not empty and not false:
For multiple branches, elif and else can be used like in Python. You can use more complex Expressions there, too:
If can also be used as an inline expression and for loop filtering .
Macros are comparable with functions in regular programming languages. They are useful to put often used idioms into reusable functions to not repeat yourself (“DRY”).
Here’s a small example of a macro that renders a form element:
The macro can then be called like a function in the namespace:
If the macro was defined in a different template, you have to import it first.
Inside macros, you have access to three special variables:
If more positional arguments are passed to the macro than accepted by the macro, they end up in the special varargs variable as a list of values.
Like varargs but for keyword arguments. All unconsumed keyword arguments are stored in this special variable.
If the macro was called from a call tag, the caller is stored in this variable as a callable macro.
Macros also expose some of their internal details. The following attributes are available on a macro object:
The name of the macro. {{ input.name }} will print input .
A tuple of the names of arguments the macro accepts.
This is true if the macro accepts extra keyword arguments (i.e.: accesses the special kwargs variable).
This is true if the macro accepts extra positional arguments (i.e.: accesses the special varargs variable).
This is true if the macro accesses the special caller variable and may be called from a call tag.
If a macro name starts with an underscore, it’s not exported and can’t be imported.
In some cases it can be useful to pass a macro to another macro. For this purpose, you can use the special call block. The following example shows a macro that takes advantage of the call functionality and how it can be used:
It’s also possible to pass arguments back to the call block. This makes it useful as a replacement for loops. Generally speaking, a call block works exactly like a macro without a name.
Here’s an example of how a call block can be used with arguments:
Filter sections allow you to apply regular Jinja filters on a block of template data. Just wrap the code in the special filter section:
Inside code blocks, you can also assign values to variables. Assignments at top level (outside of blocks, macros or loops) are exported from the template like top level macros and can be imported by other templates.
Assignments use the set tag and can have multiple targets:
Scoping Behavior
Please keep in mind that it is not possible to set variables inside a block and have them show up outside of it. This also applies to loops. The only exception to that rule are if statements which do not introduce a scope. As a result the following template is not going to do what you might expect:
It is not possible with Jinja syntax to do this. Instead use alternative constructs like the loop else block or the special loop variable:
As of version 2.10 more complex use cases can be handled using namespace objects which allow propagating of changes across scopes:
Note that the obj.attr notation in the set tag is only allowed for namespace objects; attempting to assign an attribute on any other object will raise an exception.
New in version 2.10: Added support for namespace objects
New in version 2.8.
Starting with Jinja 2.8, it’s possible to also use block assignments to capture the contents of a block into a variable name. This can be useful in some situations as an alternative for macros. In that case, instead of using an equals sign and a value, you just write the variable name and then everything until {% endset %} is captured.
The navigation variable then contains the navigation HTML source.
Changed in version 2.10.
Starting with Jinja 2.10, the block assignment supports filters.
The extends tag can be used to extend one template from another. You can have multiple extends tags in a file, but only one of them may be executed at a time.
See the section about Template Inheritance above.
Blocks are used for inheritance and act as both placeholders and replacements at the same time. They are documented in detail in the Template Inheritance section.
The include tag is useful to include a template and return the rendered contents of that file into the current namespace:
Included templates have access to the variables of the active context by default. For more details about context behavior of imports and includes, see Import Context Behavior .
From Jinja 2.2 onwards, you can mark an include with ignore missing ; in which case Jinja will ignore the statement if the template to be included does not exist. When combined with with or without context , it must be placed before the context visibility statement. Here are some valid examples:
New in version 2.2.
You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be included. If ignore missing is given, it will fall back to rendering nothing if none of the templates exist, otherwise it will raise an exception.
Changed in version 2.4: If a template object was passed to the template context, you can include that object using include .
Jinja supports putting often used code into macros. These macros can go into different templates and get imported from there. This works similarly to the import statements in Python. It’s important to know that imports are cached and imported templates don’t have access to the current template variables, just the globals by default. For more details about context behavior of imports and includes, see Import Context Behavior .
There are two ways to import templates. You can import a complete template into a variable or request specific macros / exported variables from it.
Imagine we have a helper module that renders forms (called forms.html ):
The easiest and most flexible way to access a template’s variables and macros is to import the whole template module into a variable. That way, you can access the attributes:
Alternatively, you can import specific names from a template into the current namespace:
Macros and variables starting with one or more underscores are private and cannot be imported.
Changed in version 2.4: If a template object was passed to the template context, you can import from that object.
By default, included templates are passed the current context and imported templates are not. The reason for this is that imports, unlike includes, are cached; as imports are often used just as a module that holds macros.
This behavior can be changed explicitly: by adding with context or without context to the import/include directive, the current context can be passed to the template and caching is disabled automatically.
Here are two examples:
In Jinja 2.0, the context that was passed to the included template did not include variables defined in the template. As a matter of fact, this did not work:
The included template render_box.html is not able to access box in Jinja 2.0. As of Jinja 2.1, render_box.html is able to do so.
Jinja allows basic expressions everywhere. These work very similarly to regular Python; even if you’re not working with Python you should feel comfortable with it.
The simplest form of expressions are literals. Literals are representations for Python objects such as strings and numbers. The following literals exist:
Everything between two double or single quotes is a string. They are useful whenever you need a string in the template (e.g. as arguments to function calls and filters, or just to extend or include a template).
Integers are whole numbers without a decimal part. The ‘_’ character can be used to separate groups for legibility.
Floating point numbers can be written using a ‘.’ as a decimal mark. They can also be written in scientific notation with an upper or lower case ‘e’ to indicate the exponent part. The ‘_’ character can be used to separate groups for legibility, but cannot be used in the exponent part.
Everything between two brackets is a list. Lists are useful for storing sequential data to be iterated over. For example, you can easily create a list of links using lists and tuples for (and with) a for loop:
Tuples are like lists that cannot be modified (“immutable”). If a tuple only has one item, it must be followed by a comma ( ('1-tuple',) ). Tuples are usually used to represent items of two or more elements. See the list example above for more details.
A dict in Python is a structure that combines keys and values. Keys must be unique and always have exactly one value. Dicts are rarely used in templates; they are useful in some rare cases such as the xmlattr() filter.
true is always true and false is always false.
The special constants true , false , and none are indeed lowercase. Because that caused confusion in the past, ( True used to expand to an undefined variable that was considered false), all three can now also be written in title case ( True , False , and None ). However, for consistency, (all Jinja identifiers are lowercase) you should use the lowercase versions.
Jinja allows you to calculate with values. This is rarely useful in templates but exists for completeness’ sake. The following operators are supported:
Adds two objects together. Usually the objects are numbers, but if both are strings or lists, you can concatenate them this way. This, however, is not the preferred way to concatenate strings! For string concatenation, have a look-see at the ~ operator. {{ 1 + 1 }} is 2 .
Subtract the second number from the first one. {{ 3 - 2 }} is 1 .
Divide two numbers. The return value will be a floating point number. {{ 1 / 2 }} is {{ 0.5 }} .
Divide two numbers and return the truncated integer result. {{ 20 // 7 }} is 2 .
Calculate the remainder of an integer division. {{ 11 % 7 }} is 4 .
Multiply the left operand with the right one. {{ 2 * 2 }} would return 4 . This can also be used to repeat a string multiple times. {{ '=' * 80 }} would print a bar of 80 equal signs.
Raise the left operand to the power of the right operand. {{ 2**3 }} would return 8 .
Unlike Python, chained pow is evaluated left to right. {{ 3**3**3 }} is evaluated as (3**3)**3 in Jinja, but would be evaluated as 3**(3**3) in Python. Use parentheses in Jinja to be explicit about what order you want. It is usually preferable to do extended math in Python and pass the results to render rather than doing it in the template.
This behavior may be changed in the future to match Python, if it’s possible to introduce an upgrade path.
Compares two objects for equality.
Compares two objects for inequality.
true if the left hand side is greater than the right hand side.
true if the left hand side is greater or equal to the right hand side.
true if the left hand side is lower than the right hand side.
true if the left hand side is lower or equal to the right hand side.
For if statements, for filtering, and if expressions, it can be useful to combine multiple expressions:
Return true if the left and the right operand are true.
Return true if the left or the right operand are true.
negate a statement (see below).
Parentheses group an expression.
The is and in operators support negation using an infix notation, too: foo is not bar and foo not in bar instead of not foo is bar and not foo in bar . All other expressions require a prefix notation: not (foo and bar).
The following operators are very useful but don’t fit into any of the other two categories:
Perform a sequence / mapping containment test. Returns true if the left operand is contained in the right. {{ 1 in [1, 2, 3] }} would, for example, return true.
Performs a test .
Applies a filter .
Converts all operands into strings and concatenates them.
{{ "Hello " ~ name ~ "!" }} would return (assuming name is set to 'John' ) Hello John! .
Call a callable: {{ post.render() }} . Inside of the parentheses you can use positional arguments and keyword arguments like in Python:
{{ post.render(user, full=true) }} .
Get an attribute of an object. (See Variables )
It is also possible to use inline if expressions. These are useful in some situations. For example, you can use this to extend from one template if a variable is defined, otherwise from the default layout template:
The general syntax is <do something> if <something is true> else <do something else> .
The else part is optional. If not provided, the else block implicitly evaluates into an Undefined object (regardless of what undefined in the environment is set to):
You can also use any of the methods defined on a variable’s type. The value returned from the method invocation is used as the value of the expression. Here is an example that uses methods defined on strings (where page.title is a string):
This works for methods on user-defined types. For example, if variable f of type Foo has a method bar defined on it, you can do the following:
Operator methods also work as expected. For example, % implements printf-style for strings:
Although you should prefer the .format method for that case (which is a bit contrived in the context of rendering a template):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Return the absolute value of the argument.
Get an attribute of an object. foo|attr("bar") works like foo.bar just that always an attribute is returned and items are not looked up.
See Notes on subscriptions for more details.
A filter that batches items. It works pretty much like slice just the other way round. It returns a list of lists with the given number of items. If you provide a second parameter this is used to fill up missing items. See this example:
Capitalize a value. The first character will be uppercase, all others lowercase.
Centers the value in a field of a given width.
If the value is undefined it will return the passed default value, otherwise the value of the variable:
This will output the value of my_variable if the variable was defined, otherwise 'my_variable is not defined' . If you want to use default with variables that evaluate to false you have to set the second parameter to true :
Changed in version 2.11: It’s now possible to configure the Environment with ChainableUndefined to make the default filter work on nested elements and attributes that may contain undefined values in the chain without getting an UndefinedError .
Sort a dict and yield (key, value) pairs. Python dicts may not be in the order you want to display them in, so sort them first.
Replace the characters & , < , > , ' , and " in the string with HTML-safe sequences. Use this if you need to display text that might contain such characters in HTML.
If the object has an __html__ method, it is called and the return value is assumed to already be safe for HTML.
s – An object to be converted to a string and escaped.
A Markup string with the escaped text.
Format the value like a ‘human-readable’ file size (i.e. 13 kB, 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega, Giga, etc.), if the second parameter is set to True the binary prefixes are used (Mebi, Gibi).
Return the first item of a sequence.
Convert the value into a floating point number. If the conversion doesn’t work it will return 0.0 . You can override this default using the first parameter.
Enforce HTML escaping. This will probably double escape variables.
Apply the given values to a printf-style format string, like string % values .
In most cases it should be more convenient and efficient to use the % operator or str.format() .
Group a sequence of objects by an attribute using Python’s itertools.groupby() . The attribute can use dot notation for nested access, like "address.city" . Unlike Python’s groupby , the values are sorted first so only one group is returned for each unique value.
For example, a list of User objects with a city attribute can be rendered in groups. In this example, grouper refers to the city value of the group.
groupby yields namedtuples of (grouper, list) , which can be used instead of the tuple unpacking above. grouper is the value of the attribute, and list is the items with that value.
You can specify a default value to use if an object in the list does not have the given attribute.
Changed in version 3.0: Added the default parameter.
Changed in version 2.6: The attribute supports dot notation for nested access.
Return a copy of the string with each line indented by 4 spaces. The first line and blank lines are not indented by default.
width – Number of spaces, or a string, to indent by.
first – Don’t skip indenting the first line.
blank – Don’t skip indenting empty lines.
Changed in version 3.0: width can be a string.
Changed in version 2.10: Blank lines are not indented by default.
Rename the indentfirst argument to first .
Convert the value into an integer. If the conversion doesn’t work it will return 0 . You can override this default using the first parameter. You can also override the default base (10) in the second parameter, which handles input with prefixes such as 0b, 0o and 0x for bases 2, 8 and 16 respectively. The base is ignored for decimal numbers and non-string values.
Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter:
It is also possible to join certain attributes of an object:
New in version 2.6: The attribute parameter was added.
Return the last item of a sequence.
Note: Does not work with generators. You may want to explicitly convert it to a list:
Return the number of items in a container.
Convert the value into a list. If it was a string the returned list will be a list of characters.
Convert a value to lowercase.
Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames:
Alternatively you can let it invoke a filter by passing the name of the filter and the arguments afterwards. A good example would be applying a text conversion filter on a sequence:
Similar to a generator comprehension such as:
Changed in version 2.11.0: Added the default parameter.
New in version 2.7.
Return the largest item from the sequence.
case_sensitive – Treat upper and lower case strings as distinct.
attribute – Get the object with the max value of this attribute.
Return the smallest item from the sequence.
attribute – Get the object with the min value of this attribute.
Pretty print a variable. Useful for debugging.
Return a random item from the sequence.
Filters a sequence of objects by applying a test to each object, and rejecting the objects with the test succeeding.
If no test is specified, each object will be evaluated as a boolean.
Example usage:
Filters a sequence of objects by applying a test to the specified attribute of each object, and rejecting the objects with the test succeeding.
If no test is specified, the attribute’s value will be evaluated as a boolean.
Return a copy of the value with all occurrences of a substring replaced with a new one. The first argument is the substring that should be replaced, the second is the replacement string. If the optional third argument count is given, only the first count occurrences are replaced:
Reverse the object or return an iterator that iterates over it the other way round.
Round the number to a given precision. The first parameter specifies the precision (default is 0 ), the second the rounding method:
'common' rounds either up or down
'ceil' always rounds up
'floor' always rounds down
If you don’t specify a method 'common' is used.
Note that even if rounded to 0 precision, a float is returned. If you need a real integer, pipe it through int :
Mark the value as safe which means that in an environment with automatic escaping enabled this variable will not be escaped.
Filters a sequence of objects by applying a test to each object, and only selecting the objects with the test succeeding.
Filters a sequence of objects by applying a test to the specified attribute of each object, and only selecting the objects with the test succeeding.
Slice an iterator and return a list of lists containing those items. Useful if you want to create a div containing three ul tags that represent columns:
If you pass it a second argument it’s used to fill missing values on the last iteration.
Sort an iterable using Python’s sorted() .
reverse – Sort descending instead of ascending.
case_sensitive – When sorting strings, sort upper and lower case separately.
attribute – When sorting objects or dicts, an attribute or key to sort by. Can use dot notation like "address.city" . Can be a list of attributes like "age,name" .
The sort is stable, it does not change the relative order of elements that compare equal. This makes it is possible to chain sorts on different attributes and ordering.
As a shortcut to chaining when the direction is the same for all attributes, pass a comma separate list of attributes.
Changed in version 2.11.0: The attribute parameter can be a comma separated list of attributes, e.g. "age,name" .
Changed in version 2.6: The attribute parameter was added.
Convert an object to a string if it isn’t already. This preserves a Markup string rather than converting it back to a basic string, so it will still be marked as safe and won’t be escaped again.
Strip SGML/XML tags and replace adjacent whitespace by one space.
Returns the sum of a sequence of numbers plus the value of parameter ‘start’ (which defaults to 0). When the sequence is empty it returns start.
It is also possible to sum up only certain attributes:
Changed in version 2.6: The attribute parameter was added to allow suming up over attributes. Also the start parameter was moved on to the right.
Return a titlecased version of the value. I.e. words will start with uppercase letters, all remaining characters are lowercase.
Serialize an object to a string of JSON, and mark it safe to render in HTML. This filter is only for use in HTML documents.
The returned string is safe to render in HTML documents and <script> tags. The exception is in HTML attributes that are double quoted; either use single quotes or the |forceescape filter.
value – The object to serialize to JSON.
indent – The indent parameter passed to dumps , for pretty-printing the value.
New in version 2.9.
Strip leading and trailing characters, by default whitespace.
Return a truncated copy of the string. The length is specified with the first parameter which defaults to 255 . If the second parameter is true the filter will cut the text at length. Otherwise it will discard the last word. If the text was in fact truncated it will append an ellipsis sign ( "..." ). If you want a different ellipsis sign than "..." you can specify it using the third parameter. Strings that only exceed the length by the tolerance margin given in the fourth parameter will not be truncated.
The default leeway on newer Jinja versions is 5 and was 0 before but can be reconfigured globally.
Returns a list of unique items from the given iterable.
The unique items are yielded in the same order as their first occurrence in the iterable passed to the filter.
attribute – Filter objects with unique values for this attribute.
Convert a value to uppercase.
Quote data for use in a URL path or query using UTF-8.
Basic wrapper around urllib.parse.quote() when given a string, or urllib.parse.urlencode() for a dict or iterable.
value – Data to quote. A string will be quoted directly. A dict or iterable of (key, value) pairs will be joined as a query string.
When given a string, “/” is not quoted. HTTP servers treat “/” and “%2F” equivalently in paths. If you need quoted slashes, use the |replace("/", "%2F") filter.
Convert URLs in text into clickable links.
This may not recognize links in some situations. Usually, a more comprehensive formatter, such as a Markdown library, is a better choice.
Works on http:// , https:// , www. , mailto: , and email addresses. Links with trailing punctuation (periods, commas, closing parentheses) and leading punctuation (opening parentheses) are recognized excluding the punctuation. Email addresses that include header fields are not recognized (for example, mailto:address@example.com?cc=copy@example.com ).
value – Original text containing URLs to link.
trim_url_limit – Shorten displayed URL values to this length.
nofollow – Add the rel=nofollow attribute to links.
target – Add the target attribute to links.
rel – Add the rel attribute to links.
extra_schemes – Recognize URLs that start with these schemes in addition to the default behavior. Defaults to env.policies["urlize.extra_schemes"] , which defaults to no extra schemes.
Changed in version 3.0: The extra_schemes parameter was added.
Changed in version 3.0: Generate https:// links for URLs without a scheme.
Changed in version 3.0: The parsing rules were updated. Recognize email addresses with or without the mailto: scheme. Validate IP addresses. Ignore parentheses and brackets in more cases.
Changed in version 2.8: The target parameter was added.
Count the words in that string.
Wrap a string to the given width. Existing newlines are treated as paragraphs to be wrapped separately.
s – Original text to wrap.
width – Maximum length of wrapped lines.
break_long_words – If a word is longer than width , break it across lines.
break_on_hyphens – If a word contains hyphens, it may be split across lines.
wrapstring – String to join each wrapped line. Defaults to Environment.newline_sequence .
Changed in version 2.11: Existing newlines are treated as paragraphs wrapped separately.
Changed in version 2.11: Added the break_on_hyphens parameter.
Changed in version 2.7: Added the wrapstring parameter.
Create an SGML/XML attribute string based on the items in a dict. All values that are neither none nor undefined are automatically escaped:
Results in something like this:
As you can see it automatically prepends a space in front of the item if the filter returned something unless the second parameter is false.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Return true if the object is a boolean value.
New in version 2.11.
Return whether the object is callable (i.e., some kind of function).
Note that classes are callable, as are instances of classes with a __call__() method.
Return true if the variable is defined:
See the default() filter for a simple way to set undefined variables.
Check if a variable is divisible by a number.
Same as a == b.
== , equalto
Check if the value is escaped.
Return true if the variable is even.
Return true if the object is False.
Check if a filter exists by name. Useful if a filter may be optionally available.
New in version 3.0.
Return true if the object is a float.
Same as a >= b.
Same as a > b.
> , greaterthan
Check if value is in seq.
New in version 2.10.
Return true if the object is an integer.
Check if it’s possible to iterate over an object.
Same as a <= b.
Return true if the variable is lowercased.
Same as a < b.
< , lessthan
Return true if the object is a mapping (dict etc.).
New in version 2.6.
Same as a != b.
Return true if the variable is none.
Return true if the variable is a number.
Return true if the variable is odd.
Check if an object points to the same memory address than another object:
Return true if the variable is a sequence. Sequences are variables that are iterable.
Return true if the object is a string.
Check if a test exists by name. Useful if a test may be optionally available.
Return true if the object is True.
Like defined() but the other way round.
Return true if the variable is uppercased.
The following functions are available in the global scope by default:
Return a list containing an arithmetic progression of integers. range(i, j) returns [i, i+1, i+2, ..., j-1] ; start (!) defaults to 0 . When step is given, it specifies the increment (or decrement). For example, range(4) and range(0, 4, 1) return [0, 1, 2, 3] . The end point is omitted! These are exactly the valid indices for a list of 4 elements.
This is useful to repeat a template block multiple times, e.g. to fill a list. Imagine you have 7 users in the list but you want to render three empty items to enforce a height with CSS:
Generates some lorem ipsum for the template. By default, five paragraphs of HTML are generated with each paragraph between 20 and 100 words. If html is False, regular text is returned. This is useful to generate simple contents for layout testing.
A convenient alternative to dict literals. {'foo': 'bar'} is the same as dict(foo='bar') .
Cycle through values by yielding them one at a time, then restarting once the end is reached.
Similar to loop.cycle , but can be used outside loops or across multiple loops. For example, render a list of folders and files in a list, alternating giving them “odd” and “even” classes.
items – Each positional argument will be yielded in the order given for each cycle.
New in version 2.1.
Return the current item. Equivalent to the item that will be returned next time next() is called.
Return the current item, then advance current to the next item.
Resets the current item to the first item.
A tiny helper that can be used to “join” multiple sections. A joiner is passed a string and will return that string every time it’s called, except the first time (in which case it returns an empty string). You can use this to join things:
Creates a new container that allows attribute assignment using the {% set %} tag:
The main purpose of this is to allow carrying a value from within a loop body to an outer scope. Initial values can be provided as a dict, as keyword arguments, or both (same behavior as Python’s dict constructor):
The following sections cover the built-in Jinja extensions that may be enabled by an application. An application could also provide further extensions not covered by this documentation; in which case there should be a separate document explaining said extensions .
If the i18n Extension is enabled, it’s possible to mark text in the template as translatable. To mark a section as translatable, use a trans block:
Inside the block, no statements are allowed, only text and simple variable tags.
Variable tags can only be a name, not attribute access, filters, or other expressions. To use an expression, bind it to a name in the trans tag for use in the block.
To bind more than one expression, separate each with a comma ( , ).
To pluralize, specify both the singular and plural forms separated by the pluralize tag.
By default, the first variable in a block is used to determine whether to use singular or plural form. If that isn’t correct, specify the variable used for pluralizing as a parameter to pluralize .
When translating blocks of text, whitespace and linebreaks result in hard to read and error-prone translation strings. To avoid this, a trans block can be marked as trimmed, which will replace all linebreaks and the whitespace surrounding them with a single space and remove leading and trailing whitespace.
This results in This is %(book_title)s. You should read it! in the translation file.
If trimming is enabled globally, the notrimmed modifier can be used to disable it for a block.
New in version 2.10: The trimmed and notrimmed modifiers have been added.
It’s possible to translate strings in expressions with these functions:
gettext : translate a single string
ngettext : translate a pluralizable string
_ : alias for gettext
You can print a translated string like this:
To use placeholders, use the format filter.
Always use keyword arguments to format , as other languages may not use the words in the same order.
If New Style Gettext calls are activated, using placeholders is easier. Formatting is part of the gettext call instead of using the format filter.
The ngettext function’s format string automatically receives the count as a num parameter in addition to the given parameters.
If the expression-statement extension is loaded, a tag called do is available that works exactly like the regular variable expression ( {{ ... }} ); except it doesn’t print anything. This can be used to modify lists:
If the application enables the Loop Controls , it’s possible to use break and continue in loops. When break is reached, the loop is terminated; if continue is reached, the processing is stopped and continues with the next iteration.
Here’s a loop that skips every second item:
Likewise, a loop that stops processing after the 10th iteration:
Note that loop.index starts with 1, and loop.index0 starts with 0 (See: For ).
If the Debug Extension is enabled, a {% debug %} tag will be available to dump the current context as well as the available filters and tests. This is useful to see what’s available to use in the template without setting up a debugger.
New in version 2.3.
The with statement makes it possible to create a new inner scope. Variables set within this scope are not visible outside of the scope.
With in a nutshell:
Because it is common to set variables at the beginning of the scope, you can do that within the with statement. The following two examples are equivalent:
An important note on scoping here. In Jinja versions before 2.9 the behavior of referencing one variable to another had some unintended consequences. In particular one variable could refer to another defined in the same with block’s opening statement. This caused issues with the cleaned up scoping behavior and has since been improved. In particular in newer Jinja versions the following code always refers to the variable a from outside the with block:
In earlier Jinja versions the b attribute would refer to the results of the first attribute. If you depend on this behavior you can rewrite it to use the set tag:
In older versions of Jinja (before 2.9) it was required to enable this feature with an extension. It’s now enabled by default.
New in version 2.4.
If you want you can activate and deactivate the autoescaping from within the templates.
After an endautoescape the behavior is reverted to what it was before.
# tl;dr (on this video...).
(opens new window)
Learn how to create variables inside a template, so that you can calculate values and re-use them in multiple places within a template.
So far, we've learned that we can use variables in Jinja2 templates, as long as those variables are passed in by our Python code. Like this:
Then we can use the todos variable in the template:
But did you know you can also create variables in a Jinja2 template?
It's not something we do very often, because usually in templates it's just easier to use the value rather than create a variable for it.
But there are some uses, such as when you're going to have to calculate a value multiple times.
Imagine we want to tell a user how many to-dos they have left to do:
The code won't run because we can't do len(todos) in Jinja2, but you get the idea.
Here we're creating a variable to hold the amount of to-dos so that we don't have to calculate it in two places: the if statement and the paragraph tag.
So... why can we not do len(todos) ?
It's because Jinja2 isn't Python code, and the len() function doesn't exist in Jinja2.
Instead, we have to use Jinja2 filters. Let's talk about them in the next lecture.
We'll have app.py and templates/home.html .
Inside app.py :
And inside templates/home.html :
Here we talk about defining variables in Jinja2.
Here we talk about creating variables and what its purpose is.
The code at the end of this lecture doesn't run, because we can't do len(todos) in Jinja2. We need to use a Jinja2 filter, which we'll talk about in the next lecture.
← Welcome to Jinja2 Mastery, Level 1 Working with filters in Jinja2 →
Welcome! This site is currently in beta. Get 10% off everything with promo code BETA10.
It's just html, flask render_template, flexible placeholders, jinja if , else, extends and block, jinja comments, what's next: style points, summary: how to use the jinja template engine, template inheritance faq.
Hopefully, in the last section, you've gotten comfortable with the basics of how to make a Flask app and how to go about making basic routes .
But get ready, because you're about to go from 0 to 60 in this course. You'll be picking up the pace going forward. There won't be full code examples, but there will be code snippets with enough information to guide you through to making a full Flask app. As long as you read carefully, or ask for guidance on Discord or from your mentor, you should be just fine!
How did you do with making your own routes ? Did you try adding some flavor with HTML to make it look more professional? Did your wrists start getting sore reaching for those angle brackets all the time? Seems like a pain, right?
Having to make a brand new HTML string every time you want to make a new route feels very tedious. But here's the great news with Flask: You don't have to do that all the time! This lesson introduces the Jinja2 template engine to make your life easier!
The only job of our view functions should be to generate a response to a request; that's it. Having to also make the pages? What a pain! For that, the creators of Flask also built Jinja , also called Jinja2, which is a Flask template engine.
Flask templates are files that contain the text of a response. Pages that say things like, "Upload your corn flake collection here!" are great, but that's only text.
Templates also support placeholder variables for the dynamic parts of the page, meaning those that change depending on the context of a request (whose corn flake collection, if the corn flakes are gluten-free, etc). These variables get replaced with real values through a process called rendering . And that's what Jinja's job is, to take the values those variables should take on passed in from Flask, then render those values in with the surrounding text. Let's try this thing out!
Before you get started, make a folder named templates , which will live right inside your flask-webdev directory. That's because, by default, Flask looks for your templates in a folder called exactly that: templates . Once you've done that, you're ready to go!
First things first, let's get a simple template rendered. Think of a template as just an HTML file. Make a new template file, templates/index.html . Put in the following:
Now in your hello.py , you'll need to import render_template , then replace your index() function:
With the render_template() function, all you need to do is indicate the path to the template relative to your templates folder, which is simply "index.html" . When a request is received for the index page and render_template() is called, Flask will enlist the help of Jinja2 to render the template.
Let 'er rip! Run the app with flask run and watch as you get the same output. A little boring, huh? Just wait, you're gonna go dynamic .
While a template is pretty much HTML, it's also a little more than that with Jinja. To help demonstrate, let's make another route, this time a dynamic one. Feel free to use one you might have made before in order to complete this next part.
The render_template() has more power than it might look. This function utilizes the well-known Pythonism known as keyword arguments , often seen as **kwargs in the wild. To call the function in the previous user() function example and still get the same effect, you'd do this:
In this example, you indicate which template you want Jinja to render and also pass in our name parameter along to Jinja. The name on the left side of the = is what Jinja will use as the placeholder name inside the template. The other name on the right side is the variable in the function scope.
Now when you load the user.html template, you'll see—whah!? You say you haven't made such a template yet that can handle this passed-in variable? Oh dear, let's take care of that right away!
From the last lesson, you know from believing your nomadic Flask course creator and all his sage, vast wisdom (who couldn't quite type the previous with a straight face) that the Jinja template engine can handle variables as long as the Flask application does its part by passing them over. For a simple but dynamic page that does this relay, the view function would look like this:
Crack open a new user.html template file and crack your knuckles 'cause here's the template content:
Wuzzat?! Looks like some weird HTML, but this is how Jinja likes its variables prepared for breakfast. Er, to render. The double curly brackets {{}} tell Jinja that whatever's inside them is a placeholder that should have a value assigned to it, and to render the template with that value instead. If you head to localhost:5000/user/Tom in your browser, you'll be greeted as Tom, even though that's probably not your name!
Here's the really neat thing: you can type almost anything Pythonic in these placeholder sections, and Jinja will know how to render it. Even cooler, you can put these placeholders almost anywhere in the template, and Jinja will still expand them to their actual values. That is, as long as you pass every value Jinja needs to render into the template. Here are some other other examples:
Dictionaries, indexing a list with another variable, changes to styling, even calling object methods. All of it works in a placeholder if it's 1) Python code and 2) Jinja knows about it.
Oh, and one more thing! Jinja also includes filters which can go after a variable with a pipe character in between. For that last example about screaming, you can also do the following to get the same result:
upper is just one filter to choose from, but here are some others:
Filter name | Description |
---|---|
Uppercase the first character | |
Lowercase all characters | |
Render value without applying escaping | |
Remove any HTML tags before rendering | |
Return a titlecased version of the value | |
Strip leading and trailing characters | |
Uppercase all characters |
You just learned about variables in Jinja, but don't you want more control over your templates? You're in luck because coming up, you'll apply control structures to your templates.
You were just introduced to variables in Jinja and how they put the power of Python into your templates, but there must be more, right? There is, and in this section, you'll get to know the control structures that Jinja provides for you—the if s, the for s, and a few mores!
Python wouldn't be Python without its conditionals and control flow. And it turns out Jinja wouldn't be Jinja for the same reason! Let's just go straight through what control structures Jinja has, and take note that each of these uses a {% ... %} construct:
"Should I display that element, or shouldn't I?" That, along with other hard and not-so-hard questions, can be handled with conditional statements:
Now you can know who's looking at the page! Unless they don't tell us...
Lists of elements are no match for Jinja; they shall be rendered consecutively if you so choose! These are great for using in HTML list tags.
Macros? What the heck are those? Think of them as the Jinja version of Python functions. They're great for avoiding monotonous tasks. Watch:
Automation! The best thing since sliced bread.
To copy others is necessary, but to copy oneself is pathetic. Pablo Picasso
Y'know, Picasso is onto something here. In some cases, it's extremely useful to copy one template into another, and that's exactly what Jinja's import statement does. But, "to copy oneself is pathetic?" If he's talking about Jinja, I think maybe he meant "silly."
Would some macro statements and an import or two be useful? You betcha. In fact, that's the definition of "synergy":
Defining one or more macros and one template, then importing them for painless access in another? Sweet.
Are you a Java(Script) coder? 'Cause the extends keyword makes a comeback in Jinja (if you can call it that). You're darn tootin': inheritance in templates! Using block structures, you can define and then extend or even override blocks of template code.
If you make a "base" template called base.html , you can "reserve" blocks of code to hold certain content in certain places that can be inherited later.
You'll see here that blocks of code are defined with arbitrary names, in this case, head , title , and body . Another template that extends this base template (let's call it index.html ) might look like this:
It has an extends control structure, which means it's definitely a derived template. Alrighty, try to follow along here: so you see how the title block is inside the head block in base.html ? It is outside the head block in index.html . For blocks that show up in both base and derived templates, the content in the derived template always gets used instead of the content in the base template. Here's how index.html is rendered:
These don't actually control anything, but they can be useful! Instead of using <!-- HTML comments --> for templates, it's better to use {# these comments #} , mainly because the Jinja comments won't get included in the final HTML, whereas HTML comments will get sent to the client and visible to anyone who opens the inspector.
Phew! Those are all the important control structure you'll need to be familiar with in this course. Don't worry, you'll see them again and again so you'll get used to them.
But gosh, does any of this make you feel a little uneasy? Now don't get me wrong, Flask is freakin' cool, but these pages look like they came from the Internet Stone Age, back when dial-up was a thing. And to answer the next question you almost certainly have: YES! Of course, there's an easy way to get a much prettier, modern look! Continue on with the next lessons for some serious style.
You've now dipped your toes into creating more sophisticated applications with Flask, and it looks like you're picking up steam! In this lesson, you've:
Inheritance can be tricky to wrap your head around, so here is an FAQ of common questions students have.
Here are questions that have come up from students and may come up for you. :)
Q: I inherited from bootstrap base template in template A, but when rendering template A, nothing shows up. What's wrong?
This could be because you didn't place down any block s in your inherited template. Flask-Bootstrap has pre-defined block s that are "copied" over when you use extends . Plain HTML gets overridden.
If you did place down block s, you may not have used {{ super() }} inside of it, which would override anything you defined in that block in the base template.
Q: What is the difference between <head> & <header> ?
Here's a helpful Stackoverflow post that clarifies: What is the real difference between the "head" and "header" tag?
Q: Some parts of my HTML show up twice when using blocks
This happens sometimes because you place down a parent block along with a child block inside it in the inherited template. Usually, it is enough to just place down the child block only and add the additional HTML you want to it.
Template inheritance allows you to "say a lot with just a little," meaning it gives you the capability to plop in chunks of HTML with only a couple lines of Jinja code. Within inherited templates, placing down fewer block s already pre-defined in your base template is usually better. So when in doubt, try using a subset of block s from your base template.
Q: I don't know where to start. How do I know the base template is doing what I need it to?
Let's assume you are starting with a good amount of HTML code without any Jinja. There are probably multiple HTML files that have a lot of similarities. The idea of creating a base template is to capture these similarities while still allowing for child templates to have their own content. On somewhat rare occasions, a child template may "overwrite" some parts of the HTML structure. Another nice thing about having a base template is that changes to the base template are carried over to the child templates, which saves oodles of time on the frontend so you can focus on making the backend solid.
If you're stuck, the following is a good workflow. The basis of it is to start with a bunch of already written HTML code and strip it down to the parts that are common to all templates.
First, make two copies of the index template. Name one copy as base.html and the other as index2.html . For now you'll focus on the base.html template, and you'll come back to index2.html a few steps afterward.
Create a couple of temporary routes for displaying this base template. It can be as simple as
In base.html , define block s based on the structural parts of a page. Blocks make your templates extensible and flexible, otherwise you'd have to rewrite HTML for entire pages.
a. Start with head and body to start. The head block will be defined right inside the <head> tag, which in turn contains the title, links to stylesheets and scripts, and other metadata. The body is what your users will see. Example:
b. After that, define the nested blocks, like title inside the head block and header inside the body block:
Starting to see the pattern?
c. Continue onto the next layer of nested blocks. After defining blocks for this layer, you probably have enough blocks for a decent start to a base template! Any deeper than 4 nested blocks starts to become to much. Keep in mind you don't need a block for every HTML tag; just a handful of blocks will do.
Launch your app and take a look at how your base.html template looks. Does it still look like your index page? If something doesn't look right, go back to step 3 adjust your blocks until things look the same.
From your base.html template, delete any content that is exclusive to the index page, but keep the parts that will probably be on almost every page. Things like "Welcome to my site!" would be exclusive to the index page. Things like the header and navigation bar will likely be shown on just about every page. If you're not sure if something should stay or go, err on the side of keeping it. After this, you've created the first draft of your base template!
Now you're ready to pull up index2.html . If you're using an IDE that supports side-by-side tabs like VSCode, pull up the original index.html alongside it. In index2.html , delete the existing HTML code and try to reconstruct the index page by extending index2.html from base.html and using the blocks defined within base.html . In other words, use template inheritance to re-make the index page. Remember you can check the /index2 route you made in step 2 to see how it compares to /index .
Q: I added Flask Bootstrap to my project, and now the blocks in my existing templates are screwed up when rendered. How can I fix it?
When you initialize Flask-Bootstrap in your project and inherit a template from bootstrap/base.html , it will define some blocks already, which you can see here . If you have any of these blocks in your templates, keep in mind where you do or don't have {{ super() }} .
Don't be intimidated by Flask-Bootstrap! You can actually see what Flask-Bootstrap has defined in its bootstrap/base.html template here . It's only 34 lines and might be simpler than you think.
DNMTechs – Sharing and Storing Technology Knowledge
Javascript, Python, Android, Bash, Hardware, Software and more…
Jinja is a powerful templating engine for Python that allows developers to generate dynamic content. One of the key features of Jinja is the ability to set variables within templates, enabling the creation of more flexible and customizable output. In this guide, we will explore the concept of setting variables in Jinja templates and provide examples to illustrate their usage.
Variables in Jinja templates are placeholders that can hold different values. They are defined using the {% raw %}{% set %}{% endraw %} tag, followed by the variable name and its value. Once a variable is set, it can be referenced and manipulated within the template.
In the example above, we set two variables: name with the value “John” and age with the value 25. These variables can now be used throughout the template.
Variables can be inserted into the template by enclosing them within double curly braces ( {{ variable }} ). This syntax tells Jinja to replace the placeholder with the actual value of the variable.
Hello, my name is {{ name }} and I am {{ age }} years old.
When the template is rendered, the variables will be replaced with their respective values:
Hello, my name is John and I am 25 years old.
Variables can also be manipulated within the template using various filters and functions provided by Jinja. For example, we can capitalize the first letter of the name variable using the capitalize filter:
Hello, my name is {{ name|capitalize }}.
The output will be:
Hello, my name is John.
In addition to setting variables directly within the template, Jinja also allows variables to be passed from the Python code that renders the template. This provides a way to dynamically generate content based on the values passed.
The output will be the same as before:
By passing variables to the template, we can easily customize the output based on different inputs or data retrieved from a database or an API.
Setting variables in Jinja templates is a powerful feature that enhances the flexibility and customization of dynamic content generation. By understanding how to set and use variables within templates, developers can create more dynamic and personalized output in their Python applications.
One of the main features of Jinja templates is the ability to set variables within the template itself. This allows for dynamic content generation based on the values of these variables.
In this example, we define a Jinja template that includes a variable called “name”. We then render the template by passing the value “John” to the “name” variable. The output will be “Hello, John!”.
Jinja templates also allow for the use of conditional statements to control the flow of the template. This can be useful when you want to display different content based on certain conditions.
In this example, we use the “if” statement to check if the “age” variable is greater than or equal to 18. If it is, the template will render “You are an adult”. Otherwise, it will render “You are a minor”. The output will be “You are an adult”.
Jinja templates also support looping over lists, allowing you to iterate through a collection of items and generate content dynamically.
In this example, we define a list called “items” with three elements. We then use the “for” loop to iterate over each item in the list and render it. The output will be “apple banana orange”.
Jinja templates provide a powerful way to generate dynamic content in Python applications. By setting variables, using conditional statements, and looping over lists, you can create flexible and customizable templates that can adapt to different data and conditions. With its easy syntax and integration with Python, Jinja templates are a valuable tool for any Python developer.
Reference links: – Jinja Documentation: https://jinja.palletsprojects.com/ – Real Python – Introduction to Jinja Templates: https://realpython.com/primer-on-jinja-templating/
Abstract: This article explores the usage of the set variable block in Jinja2 templates. Learn how to assign and modify values using this feature.
Jinja2 is a powerful templating language for Python that enables developers to create dynamic and reusable web page layouts. One of the key features of Jinja2 is the ability to set and manipulate variables within templates. In this article, we will explore the use of the {% set %} block in Jinja2 and how it can be used to simplify template logic and improve code readability.
The {% set %} block is a feature in Jinja2 that allows you to set and manipulate variables within a template. This block can be used to store values, perform calculations, and simplify template logic. The syntax for the {% set %} block is as follows:
Where variable_name is the name of the variable you want to set, and value is the value you want to assign to the variable. The value can be a string, number, list, dictionary, or any other Python data type.
The {% set %} block can be used in a variety of ways to simplify template logic and improve code readability. Here are some examples:
The most basic use of the {% set %} block is to store values that will be used later in the template. For example:
{{ greeting }}
The {% set %} block can also be used to perform calculations within a template. For example:
The sum is: {{ sum }}
The {% set %} block can also be used to simplify template logic by storing complex expressions or calculations in a variable. For example:
The total price is: {{ total }}
When using the {% set %} block in Jinja2, there are a few best practices to keep in mind:
The {% set %} block is a powerful feature in Jinja2 that enables developers to set and manipulate variables within templates. By using this block, you can simplify template logic, improve code readability, and reduce repetition. When using the {% set %} block, be sure to follow best practices to ensure that your code is maintainable and easy to read.
This article discusses the process of handling messages in dialogs using DialogMainForm and checks prior to TranslateMessage and DispatchMessage in C++.
Tags: : Jinja2 Templates Python SET_VAR
+48 732 022 871
Our experts are going to talk about the dimension of the social industry problems which opensource technology solves.
Variables are used to store various types of data. Their values usually depend on the location or context in which they are located. Variables can be completely independent entities or grouped together with other variables, to describe or parameterize a given object. For this purpose, we can use the structure of a dictionary , which groups variables called keys and allows you to assign values to them .
An example of such a dictionary structure in YAML can be seen below:
Variables must start with a letter, and may additionally contain numbers and the underscore character “_”. YAML allows you to reference variables within a dictionary by using the period “.” or square brackets “[]”:
Above, in both cases we referenced the value “ 2001: db8: c1sc0 :: a “. While the second is safer, the first is more often used for convenience. If we decide to use the dot “.”, it is worth checking the limitations described in the Ansible documentation .
Variables are most often used to parameterize hosts and inventory groups. Thus, they can be handled by Ansible based on the values assigned to the various variables. As the static inventory is most often created in the INI file format, we are only referring to it at the moment. When we want to assign variables directly to a host, they are given in the format “ key = value “, on the same line as the host definition. Here is an example of an inventory with variables assigned directly to hosts:
In our example, we used the names “ web1 ” and “ web2 “. If the given hostnames are not FQDN (Fully Qualified Domain Name) or IP resolvable names, then we should use the “ ansible_host ” variable. It indicates the IP address to which the connection will be established. By default, an attempt will be made to establish an SSH connection to port 22. If you want to change the port number, you must append it after a colon “ : ” to the hostname or IP address, or use the “ ansible_port ” variable.
In practice, the variables are most often defined within groups. They are then located in a special section called by the name of the group with the suffix “ :vars “. In the variable section, one variable per line is provided. Using group level variables does not exclude the possibility of using other variables or even overwriting the same variables at the host level. This is shown below:
In our example you can see the definition of the “ ansible_port ” variable for all hosts in the “ web_servers ” group. However, for host “ 10.8.232.124 ” a different port will be used as this has been overridden at the host level.
Variable definitions can span multiple scopes, that is all hosts, parent or child groups, as well as a single host. The definition of a variable within a more specific scope has higher priority . Only when it is absent, the available definitions in wider ranges are checked. In other words, as long as child groups inherit the values of the variables of the parent groups, a more precise definition always applies. Hence, at the child group level, you can override the parent group variables . If the same host belongs to many groups of the same level, the groups are arranged alphabetically and each subsequent group on the list overwrites the variables of the previous ones. It is also possible to manually set the priority for each group.
Please also note, that we may have multiple inventories. There too, the definitions of hosts and groups as well as their variables can duplicate. Both the “ ansible ” and “ ansible-playbook ” commands allow you to specify several “ -i ” or “ –inventory ” options, and as arguments you can also specify a directory with multiple inventory files (static and dynamic simultaneously). In the event that we use several inventories, each subsequent inventory on the list overwrites the variables of the previous one. When a directory is given, its files are in alphabetical order as for groups. Hence, it is then recommended to start the inventory file names with numbers, which makes the whole thing clearer.
In the case of complex environments and a large number of managed nodes, it is recommended to keep the variables out of the inventory in separate files per group and per host. The directory “ group_vars/ ” ( group variables) and the directory “ host_vars/ ” ( host variables ) are used for this purpose, respectively. Ansible tries to find these directories based on the location of the inventory file (“ ansible ” command) or the current directory (“ ansible-playbook ” command). The names of these files correspond to the names of groups or hosts. The contents of the files must conform to the YAML syntax. These files do not have to have any extension or have to have the extension: “ .yml “, “ .yaml ” or “ .json “.
In our example, the “ group_vars/web_servers ” file should contain:
Above you can see three dashes “ — ” and the typical YAML mapping “ key : value “. Variables inside the playbook can also be created in the same way. It is also possible to point to entire files and directories with variables inside it. Also, additional variables may be passed as arguments to the “ -e ” or “ –extra-vars ” options of the “ ansible ” and “ ansible-playbook ” commands. There are many possibilities, but fortunately we do not need to know them all. The full list of variable sources and their priorities is available in the Ansible documentation .
The variables are referenced through the Jinja2 template system , known to many from the Python language. It is very flexible. It supports both conditional expressions and loops. We reference the value of a variable in Jinja2 by placing its name inside double curly braces “ {{ }} “.
In the previous article , we mentioned the possibility of using the collected information from managed nodes to build more universal playbooks. This information is called facts . They are obtained during the “ Gathering Facts ” quest. It is always launched by default at the beginning of every game. During this, Ansible creates the appropriate variables for each of the nodes that can be referenced in the playbook and Jinja2 templates. The number of these variables is very large. The easiest way to view them all is to use the ad-hoc command with the “ setup ” module mentioned in the previous article in this series .
In a playbook, we usually refer to selected facts in order to condition the way of performing a given task on the value that is contained in them. It also happens that the collected facts are used as configuration values for various services or for building files. Facts can also be used to generate notifications both on the playbook exit, as well as those sent by e-mail or to the Cisco Webex Teams room.
While the playbook is running, the “ debug ” module is used to display the values of variables, including facts.
We can use one of the two options of the “ debug ” module to display the information: “ var ” or “ msg “. They are mutually exclusive, so you have to choose:
The “ debug ” module also provides the “ verbosity ” parameter, which determines the minimum debug level at which this information will be displayed for us. By default, “ verbosity ” is set to 0, which causes the information to be displayed every time the playbook is called.
Above you can see the result of making a very simple and short playbook, the content of which is slightly above it. It uses the “ debug ” module discussed above to display variables while the playbook is running.
Next, we will follow a more complex case of using variables and the Jinja2 template. We will be working on a very simple inventory that only defines 4 hosts.
None of these 4 hosts have an HTTP service running:
The task of our playbook will be to configure these 4 hosts to work as web servers. To do this, they must have the “httpd” software, an appropriately parameterized “index.html” file, an active “httpd” service and an open port for this service in the system firewall. The “index.html” file is parameterized as each of the web servers is to provide slightly different content. For this purpose, we used the Jinja2 template. Jinja2 template files should have the “.j2” extension .
In place of the Jinja2 template “ index.html.j2 ” variables , there should be appropriate values that will be collected during the “ Gathering Facts ” task. They can be different for each host. The “ template ” module is used to handle Jinja2 templates, the “ yum ” module to install the necessary software, the “ service ” module to start the service, and the “ firewalld ” module to open the appropriate port in the firewall. At this stage, I encourage you to read the output of the “ ansible-doc ” command for these modules.
The above playbook consists of two sets of tasks (“plays”) . The first deals with the configuration of web servers, and the second with the verification of what has been done. The second set is executed on “ localhost ” and has the “ Gathering Facts ” task disabled. In the first task, we assigned the contents of our inventory file “ ./inventory ” to the variable “ web_servers “. For this purpose, we have recorded the result of the appropriate “ command ” under this variable. The “ register ” parameter is used for this.
In the second task of the second set of tasks, we use the “ uri ” module to establish an HTTP connection to each of our web servers in turn. The success of this task depends on the received HTTP code. By default, the code 200 means success. Performing these tests from the “ localhost ” management station ensures that the “ httpd ” service is working and the appropriate port on the firewall has been opened.
The newly registered “ web_servers ” variable consists of many lines. Each of them is accessed via the “ web_servers.stdout_lines ” list. When we give this list as an argument to the “ loop ” expression, the module “ uri ” will be executed as many times as there are values in the list. In each subsequent invocation of the module “ uri “, the variable “ item ” will take the value of the next value in the list, which is an argument of the expression “ loop “. This is the first time we’ve used a loop in a playbook. We’ll cover loops more in the next article .
You can see in “ PLAY RECAP ” that all the tasks were successful.
Now we can repeat our test from the beginning, and check the content returned by the web servers.
Here we just covered the basics of Jinja2 variables and templates. They are a key element of playbooks and we will come back to them often in future articles.
02:09 PM, Feb 03
CEO, Network Engineer and System Administrator at networkers.pl
Marcin Ślęczek
Marcin works as CEO, Network Engineer and System Administrator at networkers.pl, which designs and implements IT Systems, Data Centers and DevOps environments. networkers.pl also sells software and hardware for building such environments and is a partner of well-known manufacturers such as Red Hat, Cisco Systems, IBM, Storware and VMware.
Computer networks, python and automation.
Welcome to part 2 of my Jinja2 Tutorial. In part 1 we learned what Jinja2 is, what are its uses, and we started looking at templating basics. Coming up next are loops and conditionals, sprinkled with tests and a healthy dose of examples!
Comparisons, logical operators, loop filtering.
In Jinja2 loops and conditionals come under name of control structures, since they affect flow of a program. Control structures use blocks enclosed by {% and %} characters.
First of the structures we'll look at is loops.
Jinja2 being a templating language has no need for wide choice of loop types so we only get for loop.
For loops start with {% for my_item in my_collection %} and end with {% endfor %} . This is very similar to how you'd loop over an iterable in Python.
Here my_item is a loop variable that will be taking values as we go over the elements. And my_collection is the name of the variable holding reference to the iterated collection.
Inside of the body of the loop we can use variable my_item in other control structures, like if conditional, or simply display it using {{ my_item }} statement.
Ok, but where would you use loops you ask? Using individual variables in your templates works fine for the most part but you might find that introducing hierarchy, and loops, will help with abstracting your data model.
For instance, prefix lists or ACLs are composed of a number of lines. It wouldn't make sense to have these lines represented as individual variables.
Initially you could model a specific prefix list using one variable per line, like so:
Which could be used in the following template:
Rendering results:
This approach, while it works, has a few problems.
If we wanted to have more lines in our prefix list we'd have to create another variable, and then another one, and so on. We not only have to add these new items to our data structure, templates would also have to have all of these new variables included individually. This is not maintainable, consumes a lot of time and is very error prone.
There is a better way, consider the below data structure:
And the template rendering prefix list configuration:
After rendering:
If you look closely you'll notice this is essentially modeling the same thing, a prefix list with a number of entries. But by using list we clearly state our intent. Even visually you can tell straight away that all of the indented lines belong to the PL_AS_65003_IN.
Adding to the prefix list here is simple, we just need to append a new line to the block. Also, our templates don't have to change at all. If we used loop to iterate, like we did here, over this list then the new lines will be picked up if we re-run the rendering. Small change but makes things a lot easier.
You might have noticed that there's still room for improvement here. Name of the prefix list is hardcoded in the prefix list definition and in our for loop. Fear not, that's something we'll be improving upon shortly.
Let's now see how we can loop over dictionaries. We will again use for loop construct, remember, that's all we've got!
We can use the same syntax we used for iterating over elements of the list but here we'll iterate over dictionary keys. To retrieve value assigned to the key we need to use subscript, i.e. [] , notation.
One advantage of using dictionaries over lists is that we can use names of elements as a reference, this makes retrieving objects and their values much easier.
Say we used list to represent our collection of interfaces:
There is no easy way of retrieving just Ethernet2 entry. We would either have to iterate over all elements and do key name comparison or we'd have to resort to advanced filters.
One thing to note, and this is hopefully becoming apparent, is that we need to spend some time modeling our data so that it's easy to work with. This is something you will rarely get right on your first attempt so don't be afraid to experiment and iterate.
Following with our example, we can keep data on individual interfaces assigned to keys in interfaces dictionary, instead of having them in a list:
Now we can access this data in our template like so:
Giving us end result:
Here intf refers to Ethernet1 and Ethernet2 keys. To access attributes of each interface we need to use interfaces[intf] notation.
There is another way of iterating over dictionary, which I personally prefer. We can retrieve key and its value at the same time by using items() method.
The end result is the same but by using items() method we simplify access to the attributes. This becomes especially important if you want to recursively iterate over deeply nested dictionaries.
I also promised to show how prefix list example can be improved upon, and that's where items() comes in.
We make small modification to our data structure by making each prefix list name a key int the dictionary prefix_lists
We now add outer loop iterating over key, value pairs in dictionary:
Rendering gives us the same result:
And here you go, no more hardcoded references to the prefix list names! If you need another prefix list you just need to add it to the prefix_lists dictionary and it will be picked up automatically by our for loop.
Note: If you're using version of Python < 3.6 then dictionaries are not ordered. That means order in which you recorded your data might differ from the order in which items will be processed inside of a template.
If you rely on the order in which they've been recorded you should either use collections.OrderedDict if using Jinja2 in Python script, or you can apply dictsort filter in your template to order your dictionary by key or value.
To sort by key:
To sort by value:
This concludes basics of looping in Jinja2 templates. The above use cases should cover 95% of your needs.
If you're looking for discussion of some advanced features connected to looping, rest assured I will be doing write up on those as well. I decided to leave more in depth Jinja2 topics for the final chapters of this tutorial and focus on the core stuff that lets you become productive quicker.
Now that we're done with loops it's time to move on to conditionals.
Jinja2 implements one type of conditional statement, the if statement. For branching out we can use elif and else .
Conditionals in Jinja2 can be used in a few different ways. We'll now have a look at some use cases and how they combine with other language features.
First thing we look at is comparing values with conditionals, these make use of ==, !=, >, >=, <, <= operators. These are pretty standard but I will show some examples nonetheless.
One common scenario where comparison is used is varying command syntax based on the version, or vendor, of the installed OS. For instance some time ago Arista had to change a number of commands due to the lawsuit and we could use a simple if statement to make sure our templates work with all of the EOS versions:
Template, vars, and rendered template for host using EOS 4.19:
And same for device running EOS 4.22:
Quite simple really yet very useful. All we did is check if recorded EOS version is less than, or greater/equal than 4.22, and this is enough to make sure correct syntax makes it to the configs.
To show more complex branching with comparisons I've got here na example of template supporting multiple routing protocols where only relevant config is generated for each device.
First we define some data for hosts.
Device running BGP:
Device running OSPF:
Device with default route only:
Then we create a template using conditionals with branching. Additional protocols choices can be easily added as needed.
Rendering results for all devices:
So there you have it, one template supporting 3 different configuration options, pretty cool.
No implementation of conditionals would be complete without logical operators. Jinja2 provides these in the form of and , or and not .
There is not an awful lot to talk about here so here's just a short example showing all of these in action:
This is is a good place to look at different variable types and their truthiness. As is the case in Python, strings, lists, dictionaries, etc., variables evaluate to True if they're not empty. For empty values evaluation results in False.
I created an example illustrating thruthiness of, non-empty and empty, string, list and dictionary:
Personally I would advise against testing non-boolean types for truthiness. There aren't that many cases where this could be useful and it might make your intent non-obvious. If you simply want to check if the variable exists then is defined test, which we'll look at shortly, is usually a better choice.
Tests in Jinja2 are used with variables and return True or False, depending on whether the value passes the test or not. To use this feature add is and test name after the variable.
The most useful test is defined which I already mentioned. This test simply checks if given variable is defined, that is if rendering engine can find it in the data it received.
Checking if variable is defined is something I use in most of my templates. Remember that by default undefined variables will simply evaluate to an empty string. By checking if variable is defined before its intended use you make sure that your template fails during rendering. Without this test you could end with incomplete document and no indication that something is amiss.
Another family of tests that I find handy are used for checking type of the variable. Certain operations require both operands to be of the same type, if they're not Jinja2 will throw an error. This applies to things like comparing numbers or iterating over lists and dictionaries.
boolean - check is variable is a boolean integer - check if variable is an integer float - check if variable is a float number - check if variable is number, will return True for both integer and float string - check if variable is a string mapping - check if variable is a mapping, i.e. dictionary iterable - check if variable can be iterated over, will match string, list, dict, etc. sequence - check if variable is a sequence
Below is an example of some variables having these tests applied:
You might've noticed that some of these tests might seem a bit ambiguous. For instance to test if variable is a list it is not enough to check if it's a sequence or an iterable. Strings also are both sequences and iterables. So are the dictionaries, even though vanilla Python classes them as Iterable and Mapping but not Sequence:
So what all of this means? Well, I suggest the following tests for each type of variable:
Number, Float, Integer - these work just as expected, so choose whatever fits your use case.
Strings - it's enough to use string test:
{{ my_string is string }}
{{ my_dict is mapping }}
{{ my_list is sequence and my list is not mapping and my list is not string }}
In some cases we know dictionary, or a string, is unlikely to appear so we can shorten the check by getting rid of mapping or string test:
{{ my_list is sequence and my list is not string }} {{ my_list is sequence and my list is not mapping }}
For the full list of available tests follow the link in References .
Last thing I wanted to touch on briefly are loop filtering and in operator.
Loop filtering does exactly what its name implies. It allows you to use if statement with for loop to skip elements that you're not interested in.
We could for instance loop over dictionary containing interfaces and process only the ones that have IP addresses:
As you can see we have 6 interfaces in total but only 4 of them have IP addresses assigned. With is defined test added to the loop we filter out interfaces with no IP addresses.
Loop filtering can be especially powerful when iterating over large payload returned from the device. In some cases you can ignore most of the elements and focus on things that are of interest.
in operator which is placed between two values can be used to check if value on the left is contained in the value on the right one. You can use it to test if an element appears in the list or if a key exists in a dictionary.
The obvious use cases for in operator is to check if something we're interested in just exists in a collection, we don't necessarily need to retrieve the item.
Looking at the previous example, we could check if Loopback0 is in the list interfaces, and if it does, we will use it to source Management Plane packets, if not we'll use Management1 interface.
Notice that even though interfaces is a dictionary containing a lot of data we didn't iterate over it or retrieve any of the keys. All we wanted to know was the presence of Loopback0 key.
To be completely honest, the above template could use some tweaking, we essentially duplicated 3 lines of config and hardcoded interface names. That's not a very good practice, and I'll show you in the next post how we can make improvements here.
And with that we've come to the end of part 2 of the Jinja2 tutorial. Next I'll cover whitespaces, so you can make your documents look just right, and we'll continue looking at the language features. I hope you learned something useful here and do come back for more!
As an example of a solution that will not work , let’s say you have a global flag ‘foundUser’ set to False, then want to iterate through a group of users, and if a condition is met inside the loop, then ‘foundUser’ would be set to True.
This will render to:
So, while you can see that inside the loop, the value of ‘foundUser’ has indeed been modified, once you get outside the loop again, the value of ‘foundUser’ is still False.
This scope behavior seems wrong to those coming from Java, Python, and most other modern programming languages. But it is unfortunately the way jinja2 works.
The workaround is that instead of setting a simple variable directly, you can instead use a dictionary. And although the dictionary object pointer itself cannot change, the key/value pair entries can be modified.
Which renders as:
http://stackoverflow.com/questions/9486393/jinja2-change-the-value-of-a-variable-inside-a-loop
http://stackoverflow.com/questions/4870346/can-a-jinja-variables-scope-extend-beyond-in-an-inner-block
https://github.com/pallets/jinja/issues/164
In Jinja2, the {% if %} statement is designed to evaluate expressions, and it does not require the use of double curly braces ( {{ }} ) within the condition. The curly braces are used for variable interpolation and expression evaluation in Jinja2, but when you are directly comparing a variable in an {% if %} statement, you just reference the variable name without the curly braces.
The reason for this design choice is to keep the syntax clean and consistent. The {% if %} statement is specifically designed to handle conditional logic and comparisons, so it expects a straightforward expression without the need for additional syntax like curly braces.
The following code snippet contains an error in the usage of Jinja2 syntax when comparing a variable within an {% if %} statement:
to fix it adjust to:
Debugging Jinja code can sometimes be challenging, but adopting good practices and leveraging helpful tools can greatly facilitate the process. Since Jinja templates are essentially a form of Python code, ensuring correct Python syntax is crucial. To check for syntax errors, use a Python linter before incorporating the code into Jinja templates.
A helpful step in the debugging process is to utilise a dedicated Jinja linter integrated into your preferred IDE. For example, if you're using Visual Studio Code, consider installing the "Jinja for Visual Studio Code" extension ( link ). Similar extensions are available for other IDEs, providing automatic detection of Jinja files and linting features as you work on your templates.
To configure the installation of the "Jinja for Visual Studio Code" extension in DevReady using a .gitpod.yml file, you can leverage the vscode section. This section allows you to specify Visual Studio Code extensions that should be installed and configured in your Gitpod workspace. Here's how you can set it up:
.gitpod.yml:
Once Gitpod detects the .gitpod.yml file in your repository, it will automatically read the configuration and install the specified Visual Studio Code extension when you open your workspace.
In addition to linting, here are some general tips for debugging Jinja code:
Check Control Structures and ensure that your control structures, such as if statements and loops, are properly closed and nested. Improperly closed or nested structures can lead to unexpected behavior.
Confirm that all the variables referenced in your Jinja code are present in the context passed to the template. Missing variables can result in errors or unexpected output.
Refer to Official Documentation here ( link ) for guidance on specific syntax and best practices. The documentation is a valuable resource for understanding Jinja's features and how to use them effectively.
By incorporating these tips and leveraging linting tools, you can streamline the debugging process and create more robust Jinja templates.
Already have an account? Login
No account yet? Create an account
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.
Sorry, we're still checking this file's contents to make sure it's safe to download. Please try again in a few minutes.
Sorry, our virus scanner detected that this file isn't safe to download.
While working on a site made with flask microframework, one of the things that kept me puzzled for hours was Jinja2’s variable overriding behavior ( variable scoping, as the pedantic will call it ). To better demonstrate my case, I am going to make two jinja templates. The first one is the base or parent template, base.html -
The child template, page.html inherits from the base.html and tries to override the slogan variable -
The output of base.html is as expected -
And the output of page.html is -
Surprise! The slogan did not get replaced in the child template! I wont dare to comment about the intuition behind this behavior, since front-end development is not my speciality. Anyway, proper clarifications came from an old documentation of jinja2 . Here’s a relevent excerpt from it:
What is happenning here is that, the slogan is first set by page.html , then again set by base.html , notice the ordering! The way to achieve the intended behavior is to change the slogan assignment in the base.html , so that it can capture the assignment done by the page.html . Here’s a version of base.html that works -
Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
The playbook below should generate a file with the content:
However, the way I construct the variable names results in either syntax/templating errors or 'variable name does not exists':
What is the proper way to 'assemble' the variable names? Or is there a better way of doing this?
My question was answered by Martin Krizek, in the Ansible newsgroup. The correct syntax is:
Not the answer you're looking for browse other questions tagged ansible yaml jinja2 ..
News and links for Django developers.
Here games is a list of dictionaries which consists of basic nba team stats such as score, win-loss etc. but it's not important for this question. It also has one attribute which consists of the team's logo name. But I'm unable to render the image from its path in scores/logos directory. This works if I directly put one of the team logo names and then the image is rendered.
How to fix this? This is what I'm doing:
By continuing, you agree to our User Agreement and acknowledge that you understand the Privacy Policy .
You’ve set up two-factor authentication for this account.
Create your username and password.
Reddit is anonymous, so your username is what you’ll go by here. Choose wisely—because once you get a name, you can’t change it.
Enter your email address or username and we’ll send you a link to reset your password
An email with a link to reset your password was sent to the email address associated with your account
Search code, repositories, users, issues, pull requests..., provide feedback.
We read every piece of feedback, and take your input very seriously.
Use saved searches to filter your results more quickly.
To see all available qualifiers, see our documentation .
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace this comment with a clear outline of what the bug is. In Jinja we can use standard python multi-variable assignments like line 3 below, which successfully evaluates but does not confer benefits of namespaces variables. However, line 4 below throws an error, Include the full traceback if there was an exception. Environment: |
The text was updated successfully, but these errors were encountered: |
Successfully merging a pull request may close this issue.
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Get early access and see previews of new features.
Any idea of how we can use dynamic variables inside the Jinja2 Template. Below is the data from my Jinja2 template.
oracle.install.asm.diskGroup.disks=/dev/oracleasm/disks/DATA,/dev/oracleasm/disks/ARCH,/dev/oracleasm/disks/OCR
The variable values in the defaults/main.yml is:
I am trying to use these variable values to pass dynamically at the time of running the playbook. These values should automatically get populated in the template.
Yes, this is possible. The main.yml will be sourced automatically when the ansible role is invoked. You just have to write a jinja2 template file for the same.
For example the below file:
A better representation of the main.yml file would be
jinja2 template: supports for loop so you can apply with_items on the above variable asm_disk_detail and create a config file as needed.
Note:- Please try the jinja2 file creation from your side in case any issues please shout :)
===============Play and jinja2 template
playbook-->
Use Ansible template module with a For loop in your template.
Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more
Post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .
COMMENTS
I would like to know how can I set a variable with another variable in jinja. I will explain, I have got a submenu and I would like show which link is active. I tried this: {% set active_link = {{
More information about assignments in jinja2 here. Or simply do the conditionals within python and pass the result to jinja2 template:
Jinja2 Tutorial - Part 1 - Introduction and variable substitution. This post is the first of the Jinja tutorial series where I'll provide an overview of the language, discussion of its features and a healthy dose of example use cases. If you're new to the world of templating, know what templates are but never used Jinja before, or simply need ...
Starting with Jinja 2.8, it's possible to also use block assignments to capture the contents of a block into a variable name. This can be useful in some situations as an alternative for macros.
Learn how to create and use new Jinja2 variables in your Flask templates. Follow the step-by-step guide and code examples.
In this Flask tutorial, learn to use the Jinja template engine, aka Jinja2. Discover how the Jinja2 Flask template works using variables, control structures, and loops.
Jinja is a powerful templating engine for Python that allows developers to generate dynamic content. One of the key features of Jinja is the ability to set variables within templates, enabling the creation of more flexible and customizable output. In this guide, we will explore the concept of setting variables in Jinja templates and provide examples to illustrate their usage.
This article explores the usage of the set variable block in Jinja2 templates. Learn how to assign and modify values using this feature.
Ansible, part IV - Variables and Jinja2 Templates. Variables are used to store various types of data. Their values usually depend on the location or context in which they are located. Variables can be completely independent entities or grouped together with other variables, to describe or parameterize a given object.
Welcome to part 2 of my Jinja2 Tutorial. In part 1 we learned what Jinja2 is, what are its uses, and we started looking at templating basics. Coming up next are loops and conditionals, sprinkled with tests and a healthy dose of examples!
When using jinja2 for SaltStack formulas you may be surprised to find that your global scoped variables do not have ability to be modified inside a loop. Although this is counter intuitive given the scope behavior of most scripting languages it is unfortunately the case that a jinja2 globally scoped variable cannot be modified from an inner scope.
The curly braces are used for variable interpolation and expression evaluation in Jinja2, but when you are directly comparing a variable in an {% if %} statement, you just reference the variable name without the curly braces. The reason for this design choice is to keep the syntax clean and consistent. The {% if %} statement is specifically ...
About variable overriding behavior of Jinja2 While working on a site made with flask microframework, one of the things that kept me puzzled for hours was Jinja2's variable overriding behavior ( variable scoping, as the pedantic will call it ). To better demonstrate my case, I am going to make two jinja templates.
The playbook below should generate a file with the content: a,b ssh_host_key ssh_rsa_host_key However, the way I construct the variable names results in either syntax/templating errors or 'variabl...
As for rationale, this would allow for rendering {% block %} content into a variable (presumably as jinja2.Markup ). Using Jinja powers, this would subsequently enable conditional and/or repeated inclusion of block content.
How to render variables within the static path in jinja templates? Here games is a list of dictionaries which consists of basic nba team stats such as score, win-loss etc. but it's not important for this question.
In Jinja we can use standard python multi-variable assignments like line 3 below, which successfully evaluates but does not confer benefits of namespaces variables.
jinja2 template: supports for loop so you can apply with_items on the above variable asm_disk_detail and create a config file as needed. Note:- Please try the jinja2 file creation from your side in case any issues please shout :)