• Jinja Documentation (3.0.x) »
  • Template Designer Documentation

Template Designer Documentation ¶

This document describes the syntax and semantics of the template engine and will be most useful as reference to those creating Jinja templates. As the template engine is very flexible, the configuration from the application can be slightly different from the code presented here in terms of delimiters and behavior of undefined values.

A Jinja template is simply a text file. Jinja can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). A Jinja template doesn’t need to have a specific extension: .html , .xml , or any other extension is just fine.

A template contains variables and/or expressions , which get replaced with values when a template is rendered ; and tags , which control the logic of the template. The template syntax is heavily inspired by Django and Python.

Below is a minimal template that illustrates a few basics using the default Jinja configuration. We will cover the details later in this document:

The following example shows the default configuration settings. An application developer can change the syntax configuration from {% foo %} to <% foo %> , or something similar.

There are a few kinds of delimiters. The default Jinja delimiters are configured as follows:

{% ... %} for Statements

{{ ... }} for Expressions to print to the template output

{# ... #} for Comments not included in the template output

Line Statements and Comments are also possible, though they don’t have default prefix characters. To use them, set line_statement_prefix and line_comment_prefix when creating the Environment .

Template File Extension ¶

As stated above, any file can be loaded as a template, regardless of file extension. Adding a .jinja extension, like user.html.jinja may make it easier for some IDEs or editor plugins, but is not required. Autoescaping, introduced later, can be applied based on file extension, so you’ll need to take the extra suffix into account in that case.

Another good heuristic for identifying templates is that they are in a templates folder, regardless of extension. This is a common layout for projects.

Variables ¶

Template variables are defined by the context dictionary passed to the template.

You can mess around with the variables in templates provided they are passed in by the application. Variables may have attributes or elements on them you can access too. What attributes a variable has depends heavily on the application providing that variable.

You can use a dot ( . ) to access attributes of a variable in addition to the standard Python __getitem__ “subscript” syntax ( [] ).

The following lines do the same thing:

It’s important to know that the outer double-curly braces are not part of the variable, but the print statement. If you access variables inside tags don’t put the braces around them.

If a variable or attribute does not exist, you will get back an undefined value. What you can do with that kind of value depends on the application configuration: the default behavior is to evaluate to an empty string if printed or iterated over, and to fail for every other operation.

Implementation

For the sake of convenience, foo.bar in Jinja does the following things on the Python layer:

check for an attribute called bar on foo ( getattr(foo, 'bar') )

if there is not, check for an item 'bar' in foo ( foo.__getitem__('bar') )

if there is not, return an undefined object.

foo['bar'] works mostly the same with a small difference in sequence:

check for an item 'bar' in foo . ( foo.__getitem__('bar') )

if there is not, check for an attribute called bar on foo . ( getattr(foo, 'bar') )

This is important if an object has an item and attribute with the same name. Additionally, the attr() filter only looks up attributes.

Variables can be modified by filters . Filters are separated from the variable by a pipe symbol ( | ) and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is applied to the next.

For example, {{ name|striptags|title }} will remove all HTML Tags from variable name and title-case the output ( title(striptags(name)) ).

Filters that accept arguments have parentheses around the arguments, just like a function call. For example: {{ listx|join(', ') }} will join a list with commas ( str.join(', ', listx) ).

The List of Builtin Filters below describes all the builtin filters.

Beside filters, there are also so-called “tests” available. Tests can be used to test a variable against a common expression. To test a variable or expression, you add is plus the name of the test after the variable. For example, to find out if a variable is defined, you can do name is defined , which will then return true or false depending on whether name is defined in the current template context.

Tests can accept arguments, too. If the test only takes one argument, you can leave out the parentheses. For example, the following two expressions do the same thing:

The List of Builtin Tests below describes all the builtin tests.

To comment-out part of a line in a template, use the comment syntax which is by default set to {# ... #} . This is useful to comment out parts of the template for debugging or to add information for other template designers or yourself:

Whitespace Control ¶

In the default configuration:

a single trailing newline is stripped if present

other whitespace (spaces, tabs, newlines etc.) is returned unchanged

If an application configures Jinja to trim_blocks , the first newline after a template tag is removed automatically (like in PHP). The lstrip_blocks option can also be set to strip tabs and spaces from the beginning of a line to the start of a block. (Nothing will be stripped if there are other characters before the start of the block.)

With both trim_blocks and lstrip_blocks enabled, you can put block tags on their own lines, and the entire block line will be removed when rendered, preserving the whitespace of the contents. For example, without the trim_blocks and lstrip_blocks options, this template:

gets rendered with blank lines inside the div:

But with both trim_blocks and lstrip_blocks enabled, the template block lines are removed and other whitespace is preserved:

You can manually disable the lstrip_blocks behavior by putting a plus sign ( + ) at the start of a block:

Similarly, you can manually disable the trim_blocks behavior by putting a plus sign ( + ) at the end of a block:

You can also strip whitespace in templates by hand. If you add a minus sign ( - ) to the start or end of a block (e.g. a For tag), a comment, or a variable expression, the whitespaces before or after that block will be removed:

This will yield all elements without whitespace between them. If seq was a list of numbers from 1 to 9 , the output would be 123456789 .

If Line Statements are enabled, they strip leading whitespace automatically up to the beginning of the line.

By default, Jinja also removes trailing newlines. To keep single trailing newlines, configure Jinja to keep_trailing_newline .

You must not add whitespace between the tag and the minus sign.

It is sometimes desirable – even necessary – to have Jinja ignore parts it would otherwise handle as variables or blocks. For example, if, with the default syntax, you want to use {{ as a raw string in a template and not start a variable, you have to use a trick.

The easiest way to output a literal variable delimiter ( {{ ) is by using a variable expression:

For bigger sections, it makes sense to mark a block raw . For example, to include example Jinja syntax in a template, you can use this snippet:

Minus sign at the end of {% raw -%} tag cleans all the spaces and newlines preceding the first character of your raw data.

Line Statements ¶

If line statements are enabled by the application, it’s possible to mark a line as a statement. For example, if the line statement prefix is configured to # , the following two examples are equivalent:

The line statement prefix can appear anywhere on the line as long as no text precedes it. For better readability, statements that start a block (such as for , if , elif etc.) may end with a colon:

Line statements can span multiple lines if there are open parentheses, braces or brackets:

Since Jinja 2.2, line-based comments are available as well. For example, if the line-comment prefix is configured to be ## , everything from ## to the end of the line is ignored (excluding the newline sign):

Template Inheritance ¶

The most powerful part of Jinja is template inheritance. Template inheritance allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override.

Sounds complicated but is very basic. It’s easiest to understand it by starting with an example.

Base Template ¶

This template, which we’ll call base.html , defines a simple HTML skeleton document that you might use for a simple two-column page. It’s the job of “child” templates to fill the empty blocks with content:

In this example, the {% block %} tags define four blocks that child templates can fill in. All the block tag does is tell the template engine that a child template may override those placeholders in the template.

block tags can be inside other blocks such as if , but they will always be executed regardless of if the if block is actually rendered.

Child Template ¶

A child template might look like this:

The {% extends %} tag is the key here. It tells the template engine that this template “extends” another template. When the template system evaluates this template, it first locates the parent. The extends tag should be the first tag in the template. Everything before it is printed out normally and may cause confusion. For details about this behavior and how to take advantage of it, see Null-Default Fallback . Also a block will always be filled in regardless of whether the surrounding condition is evaluated to be true or false.

The filename of the template depends on the template loader. For example, the FileSystemLoader allows you to access other templates by giving the filename. You can access templates in subdirectories with a slash:

But this behavior can depend on the application embedding Jinja. Note that since the child template doesn’t define the footer block, the value from the parent template is used instead.

You can’t define multiple {% block %} tags with the same name in the same template. This limitation exists because a block tag works in “both” directions. That is, a block tag doesn’t just provide a placeholder to fill - it also defines the content that fills the placeholder in the parent . If there were two similarly-named {% block %} tags in a template, that template’s parent wouldn’t know which one of the blocks’ content to use.

If you want to print a block multiple times, you can, however, use the special self variable and call the block with that name:

Super Blocks ¶

It’s possible to render the contents of the parent block by calling super() . This gives back the results of the parent block:

Nesting extends ¶

In the case of multiple levels of {% extends %} , super references may be chained (as in super.super() ) to skip levels in the inheritance tree.

For example:

Rendering child.tmpl will give body: Hi from child. Hi from parent.

Rendering grandchild1.tmpl will give body: Hi from grandchild1.

Rendering grandchild2.tmpl will give body: Hi from grandchild2. Hi from parent.

Named Block End-Tags ¶

Jinja allows you to put the name of the block after the end tag for better readability:

However, the name after the endblock word must match the block name.

Block Nesting and Scope ¶

Blocks can be nested for more complex layouts. However, per default blocks may not access variables from outer scopes:

This example would output empty <li> items because item is unavailable inside the block. The reason for this is that if the block is replaced by a child template, a variable would appear that was not defined in the block or passed to the context.

Starting with Jinja 2.2, you can explicitly specify that variables are available in a block by setting the block to “scoped” by adding the scoped modifier to a block declaration:

When overriding a block, the scoped modifier does not have to be provided.

Required Blocks ¶

Blocks can be marked as required . They must be overridden at some point, but not necessarily by the direct child template. Required blocks may only contain space and comments, and they cannot be rendered directly.

Rendering page.txt or issue.txt will raise TemplateRuntimeError because they don’t override the body block. Rendering bug_report.txt will succeed because it does override the block.

When combined with scoped , the required modifier must be placed after the scoped modifier. Here are some valid examples:

Template Objects ¶

extends , include , and import can take a template object instead of the name of a template to load. This could be useful in some advanced situations, since you can use Python code to load a template first and pass it in to render .

Note how extends is passed the variable with the template object that was passed to render , instead of a string.

HTML Escaping ¶

When generating HTML from templates, there’s always a risk that a variable will include characters that affect the resulting HTML. There are two approaches:

manually escaping each variable; or

automatically escaping everything by default.

Jinja supports both. What is used depends on the application configuration. The default configuration is no automatic escaping; for various reasons:

Escaping everything except for safe values will also mean that Jinja is escaping variables known to not include HTML (e.g. numbers, booleans) which can be a huge performance hit.

The information about the safety of a variable is very fragile. It could happen that by coercing safe and unsafe values, the return value is double-escaped HTML.

Working with Manual Escaping ¶

If manual escaping is enabled, it’s your responsibility to escape variables if needed. What to escape? If you have a variable that may include any of the following chars ( > , < , & , or " ) you SHOULD escape it unless the variable contains well-formed and trusted HTML. Escaping works by piping the variable through the |e filter:

Working with Automatic Escaping ¶

When automatic escaping is enabled, everything is escaped by default except for values explicitly marked as safe. Variables and expressions can be marked as safe either in:

The context dictionary by the application with markupsafe.Markup

The template, with the |safe filter.

If a string that you marked safe is passed through other Python code that doesn’t understand that mark, it may get lost. Be aware of when your data is marked safe and how it is processed before arriving at the template.

If a value has been escaped but is not marked safe, auto-escaping will still take place and result in double-escaped characters. If you know you have data that is already safe but not marked, be sure to wrap it in Markup or use the |safe filter.

Jinja functions (macros, super , self.BLOCKNAME ) always return template data that is marked as safe.

String literals in templates with automatic escaping are considered unsafe because native Python strings are not safe.

List of Control Structures ¶

A control structure refers to all those things that control the flow of a program - conditionals (i.e. if/elif/else), for-loops, as well as things like macros and blocks. With the default syntax, control structures appear inside {% ... %} blocks.

Loop over each item in a sequence. For example, to display a list of users provided in a variable called users :

As variables in templates retain their object properties, it is possible to iterate over containers like dict :

Python dicts may not be in the order you want to display them in. If order matters, use the |dictsort filter.

Inside of a for-loop block, you can access some special variables:

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:

Assignments ¶

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

Block Assignments ¶

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.

Import Context Behavior ¶

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.

Expressions ¶

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.

Comparisons ¶

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

Other Operators ¶

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 )

If Expression ¶

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

Python Methods ¶

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

List of Builtin Filters ¶

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.

List of Builtin Tests ¶

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.

List of Global Functions ¶

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

Extensions ¶

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.

Expression Statement ¶

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:

Loop Controls ¶

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

Debug Statement ¶

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.

With Statement ¶

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.

Autoescape Overrides ¶

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.

Logo

  • Template File Extension
  • Whitespace Control
  • Line Statements
  • Base Template
  • Child Template
  • Super Blocks
  • Nesting extends
  • Named Block End-Tags
  • Block Nesting and Scope
  • Required Blocks
  • Template Objects
  • Working with Manual Escaping
  • Working with Automatic Escaping
  • Assignments
  • Block Assignments
  • Import Context Behavior
  • Comparisons
  • Other Operators
  • If Expression
  • Python Methods
  • List of Builtin Filters
  • List of Builtin Tests
  • List of Global Functions
  • Expression Statement
  • Loop Controls
  • Debug Statement
  • With Statement
  • Autoescape Overrides
  • Next: Extensions

Quick search

  • TL;DR (on this video...)
  • Lecture contents
  • Code at the start of this lecture
  • Final code at the end of this lecture

# Creating new Jinja2 variables

# 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.

# Lecture contents

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.

# Code at the start of this lecture

We'll have app.py and templates/home.html .

Inside app.py :

And inside templates/home.html :

# Code written in this lecture

Here we talk about defining variables in Jinja2.

Here we talk about creating variables and what its purpose is.

# Final code at the end of this lecture

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.

How to Use the Jinja Template Engine

  • Introduction

What is a Flask Template?

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!

Making a Jinja2 Template

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!

Using Variables in Jinja Templates

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!

A screenshot of a browser window with the text 'Hello, Tom!' as the web page content

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!

Control Structures

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:

  • title - content is Home
  • head - the textual content is Home - My App since title is contained within head , and shows up as the page's title (the browser tab text); super() is used to bring in the content from the base class, then afterwards it is extended with a <style> tag
  • body - content is just Hello World!

A screenshot of a webpage demonstrating how the structure of the page has been extended from a base template

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:

  • Discovered that templates are your best friends for avoiding repetition and that you can use the Jinja template engine to render responses dynamically.
  • Set up a templates folder and learned how to render simple HTML templates using render_template() .
  • Understood how to pass variables to templates in Flask, enabling dynamic content to be displayed to the user, such as personalized greetings.
  • Played with dynamic placeholders in templates, learning that you can essentially run Python code in your HTML using Jinja syntax.
  • Grasped control structures in Jinja, like if , elif , else , for , and import , which allow you to add conditional logic and loops to your templates.
  • Tackled template inheritance with the extends and block keywords.
  • Touched on macros and import in Jinja, which act like functions in Python and can be reused across different templates.

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.

  • The index template is often the simplest template of the bunch, so it is easiest to start with

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 .

  • Most of the time, you won't need to change the HTML inside an inherited block, but if you do, you can redeclare it in a derived template and change or add anything you need to the block.

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 logo

DNMTechs – Sharing and Storing Technology Knowledge

Javascript, Python, Android, Bash, Hardware, Software and more…

Setting Variables in Jinja Templates: A Guide to Python 3 Programming

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.

Understanding Variables in Jinja Templates

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.

Using Variables in Jinja Templates

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.

Passing Variables to Jinja Templates

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.

Example 1: Setting a Variable in a Jinja Template

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!”.

Example 2: Using Conditional Statements in Jinja Templates

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”.

Example 3: Looping Over a List in Jinja Templates

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/

Related Posts

variable assignment in jinja2

Exploring the Accessibility of Python’s ‘Private’ Methods in Python 3 Programming

variable assignment in jinja2

Troubleshooting Arrow Key Behavior in Putty: Python 3 Programming without Colon Extension

variable assignment in jinja2

Python 3 Programming: Summing All Values in a Dictionary

Jinja2 Set Variable Block

Jinja2: Using Set Variable Block

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.

What is the Set Variable Block?

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.

Using the Set Variable Block

The {% set %} block can be used in a variety of ways to simplify template logic and improve code readability. Here are some examples:

Storing Values

The most basic use of the {% set %} block is to store values that will be used later in the template. For example:

{{ greeting }}

Performing Calculations

The {% set %} block can also be used to perform calculations within a template. For example:

The sum is: {{ sum }}

Simplifying Template Logic

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

Best Practices

When using the {% set %} block in Jinja2, there are a few best practices to keep in mind:

  • Use descriptive variable names to improve code readability.
  • Avoid setting variables within loops or conditionals, as this can make the code harder to read and debug.
  • Use the {% with %} block instead of {% set %} for complex expressions or calculations, as it can improve code readability and reduce repetition.

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.

  • Jinja2 Documentation: Set Block
  • A Primer on Jinja Templating
  • Jinja2 Documentation

Message Handling in Dialogs: Using DialogMainForm and Checks prior to TranslateMessage and DispatchMessage

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

Latest news

  • Customizing Push Notification Design with FCMAndroid/iOS
  • Filtering Query: Django's Week Day using Specific Timezone
  • Running Gemini-1.5 with Flash Jupyter Notebook on Desktop
  • Mapping Weighted Table Families to Consume One Course: A Clarification
  • Unable to Open pgAdmin 4: Server Not Responding
  • Implementing JWT Authentication in Spring Boot: A Step-by-Step Guide
  • Debugging PHP on Shared Hosting: A Possible Solution
  • ICMPv6 Solicitation Request in PHP: Socket Programming
  • Creating a Python Discord Bot for Sending Computer Mic Feedback
  • VSCode Zoom: Differences Between Normal and Web Version
  • Resolving Unsupported classfile major version 66 error in Cordova/Gradle build
  • Filtering Records Based on Multiple HTTP Path Methods
  • Resolving Webpack Compilation Errors in Cypress Tests: Docker and Jenkins
  • Fixing Excel File Directory Issues with 'filedirectoryFunction' in Software Development
  • Multithreaded Broad-Phase Collision Detection with Quad Trees: A Walkthrough
  • Writing to Event Log using PowerShell: An Example
  • Understanding Bezel ScrollView Default Behavior on Android Wear OS with Java
  • Wix: Enabling Button (button43) - Troubleshooting
  • PUT Update Doesn't Work Using Redux Toolkit in Data Frontend Slice (Goes Undefined)
  • Writing Reusable Django Apps: Installing distribute Error
  • Revalidating Data CMS Request Time in next.js 14
  • Automating Python Scripts in Crontab for MacBook Air Sleep Mode
  • A Java App with Hibernate 6: Saving User Data in PostgreSQL
  • Understanding Buffering Issues with Reading Stream and Write File in Node.js
  • Unity: Calling Property Setter for Serialized Backing Field Changed
  • Copy Activity and File3 Columns to Synapse Analytics Dedicated SQL Pool using ADF and Dynamic Column Mapping
  • Iterating Forwards and Backwards with Dependent Order Iterators in C++
  • Configuring Select2 Option HTML Dropdown with Different String Values and Text
  • 1Node Connected Pipeline: A Revolution in Software Development?
  • Empty RSS/Atom Feed Pointing to Next Chunk
  • IsRowHiddenByFilter(rowPosition) not returning true: Troubleshooting Table Filtering Issues
  • Achieving 100% Accuracy in Model Training and Testing: Decision Tree, Random Forest, SVM, KNN, Logistic Regression
  • GUI for Live Editing DataFrame: Call Functions via Buttons in Python
  • Analyzing CPU vs GPU Performance in Colab: A Comparison of Memory Consumption
  • JWT HttpOnly Cookie Problem in Angular-PHP App: A Solution

variable assignment in jinja2

+48 732 022 871

[email protected]

New upcoming webinar!

Our experts are going to talk about the dimension of the social industry problems which opensource technology solves.

variable assignment in jinja2

Ansible, part IV – Variables and Jinja2 Templates

variable assignment in jinja2

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:

variable assignment in jinja2

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 “[]”:

variable assignment in jinja2

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:

variable assignment in jinja2

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:

variable assignment in jinja2

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:

variable assignment in jinja2

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.

variable assignment in jinja2

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:

  • “ var ” only displays the value of the specified variable and does not require the explicit use of curly braces around the variable name “ {{ }} “.
  • “ msg ” displays a message prepared by us, in which if variables are used, they should be explicitly placed inside double curly braces “ {{ }} ” – according to the Jinja2 format.

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.

variable assignment in jinja2

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.

variable assignment in jinja2

None of these 4 hosts have an HTTP service running:

variable assignment in jinja2

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 .

variable assignment in jinja2

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.

variable assignment in jinja2

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 .

variable assignment in jinja2

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.

variable assignment in jinja2

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

variable assignment in jinja2

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.

TTL255 - Przemek Rogala's blog

TTL255 - Przemek Rogala's blog

Computer networks, python and automation.

  • Jinja2 Tutorial - Part 2 - Loops and conditionals

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!

Jinja2 Tutorial series

  • Jinja2 Tutorial - Part 1 - Introduction and variable substitution
  • Jinja2 Tutorial - Part 3 - Whitespace control
  • Jinja2 Tutorial - Part 4 - Template filters
  • Jinja2 Tutorial - Part 5 - Macros
  • Jinja2 Tutorial - Part 6 - Include and Import
  • J2Live - Online Jinja2 Parser

Looping over dictionaries

Comparisons, logical operators, loop filtering.

  • in Operator
  • GitHub repository with resources for this post

Control structures

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.

Conditionals and tests

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

  • Dictionary - using mapping test is sufficient:

{{ my_dict is mapping }}

  • Lists - this is a tough one, full check should tests if variable is a sequence but at the same time it cannot be a mapping or a string:

{{ 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

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!

  • Official documentation for the latest version of Jinja2 (2.11.x). Available at: https://jinja.palletsprojects.com/en/2.11.x/
  • Jinja2 built-in tests. Available at: https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-tests
  • Jinja2 Python library at PyPi. Available at: https://pypi.org/project/Jinja2/
  • GitHub repo with source code for Jinja. Available at: https://github.com/pallets/jinja/
  • GitHub repo with resources for this post. Available at: https://github.com/progala/ttl255.com/tree/master/jinja2/jinja-tutorial-p2-loops-conditionals

 alt=

SaltStack: Setting a jinja2 variable from an inner block scope

saltstack_logo-thumbnail

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

  • Knowledge base overview
  • DataOps.live Platform

Debugging Jinja2: Resolving Common Issues with Variables in {% if %} Statements

  • 6 months ago 5 February 2024

Common Challenges Encountered in Jinja {% if %} Statements

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 and Linting in Jinja Templates

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.

Best Practices

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

Login to the community

No account yet? Create an account

Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.

Scanning file for viruses.

Sorry, we're still checking this file's contents to make sure it's safe to download. Please try again in a few minutes.

This file cannot be downloaded

Sorry, our virus scanner detected that this file isn't safe to download.

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

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.

Use lookup/dynamic variable names in Ansible jinja2 template

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?

Willem's user avatar

  • Try fixing the template errors by removing the unnecessary double braces. Then maybe you can see what is going on. –  Michael Hampton Commented Jun 25, 2020 at 12:03
  • @MichaelHampton. That was one of the things I tried. In the end, Martin Krizek helped me out. Thanks. –  Willem Commented Jun 29, 2020 at 14:01

My question was answered by Martin Krizek, in the Ansible newsgroup. The correct syntax is:

You must log in to answer this question.

Not the answer you're looking for browse other questions tagged ansible yaml jinja2 ..

  • The Overflow Blog
  • Unpacking the 2024 Developer Survey results
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Introducing an accessibility dashboard and some upcoming changes to display...

Hot Network Questions

  • In Europe, are you allowed to enter an intersection on red light in order to allow emergency vehicles to pass?
  • Will lights plugged into cigarette lighter drain the battery to the point that the truck won't start?u
  • Generalized Super-Luhn
  • Do academic researchers generally not worry about their work infringing on patents? Have there been cases where they wish they had?
  • What equipment would be needed for a top of the line hacking group?
  • Significance of negative work done
  • Arduino Board Getting Too Hot: Need Help Diagnosing Issue (Schematic Provided)
  • Is it likely that Russia has made fake allegations against Tourists in the past to exchange them as prisoners?
  • How does "regina" derive from "rex"?
  • A finance broker made me the primary instead of a co-signer
  • Make a GCSE student's error work
  • What would "doctor shoes" have looked like in "Man on the Moon"?
  • Are story points really a good measure for velocity?
  • When are these base spaces isomorphic?
  • How to use Mathematica to plot following helix solid geometry?
  • dealing with the feeling after rejection
  • Why do commercial airliners go around on hard touchdown?
  • Is there a simple paradox like Russell's paradox that arises if we assume
  • What happens if your child sells your car?
  • Reportedly there are German-made infantry fighting vehicles in Russia's Kursk region. Has this provoked any backlash in Germany?
  • Positive Freedom v. Negative Freedom: a binary or a spectruum?
  • Litz Limitations
  • When is the action of a mapping class group on the set of punctures realized by a finite subgroup of mapping classes?
  • Is an infinite composition of bijections always a bijection? Also, a function iteration notation question.

variable assignment in jinja2

Get the Reddit app

News and links for Django developers.

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. 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 .

Enter the 6-digit code from your authenticator app

You’ve set up two-factor authentication for this account.

Enter a 6-digit backup code

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.

Reset your password

Enter your email address or username and we’ll send you a link to reset your password

Check your inbox

An email with a link to reset your password was sent to the email address associated with your account

Choose a Reddit account to continue

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications You must be signed in to change notification settings

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

Namespaces do not allow multi-variable assignments #1413

@kevin-brown

hans2520 commented May 10, 2021

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:

Successfully merging a pull request may close this issue.

@kevin-brown

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

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.

Using variables in the Jinja2 template in ansible Playbook

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.

D.Rosado's user avatar

2 Answers 2

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

error404's user avatar

  • Thanks for the reply..! My Template has the following line..! oracle.install.asm.diskGroup.disks=/dev/oracleasm/disks/{{ item }},/dev/oracleasm/disks/{{ item }},/dev/oracleasm/disks/{{ item }}. My vars file containes the below lines. asm_disk_detail: - { name: 'OCR', path: '/dev/sde1' } - { name: 'DATA', path: '/dev/sdf1' } - { name: 'ARCH', path: '/dev/sdg1' } The line in the template has to fetch the value from vars file, which is not working for me. I tried using For loop as well. @error404 –  IOT Commented Mar 25, 2019 at 10:42
  • @IOT Added the play, jinja2 template and the output format I am generating. Let me know in case you are looking for another output format –  error404 Commented Mar 25, 2019 at 15:22

Use Ansible template module with a For loop in your template.

sebthebert's user avatar

  • Here it,s taking the same name for the 3 variables. @sebthebert –  IOT Commented Mar 25, 2019 at 10:47

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

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 .

Not the answer you're looking for? Browse other questions tagged scripting ansible jinja2 or ask your own question .

  • The Overflow Blog
  • Unpacking the 2024 Developer Survey results
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Introducing an accessibility dashboard and some upcoming changes to display...
  • Tag hover experiment wrap-up and next steps

Hot Network Questions

  • In Europe, are you allowed to enter an intersection on red light in order to allow emergency vehicles to pass?
  • In Norway, when number ranges are listed 3 times on a sign, what do they mean?
  • What equipment would be needed for a top of the line hacking group?
  • Is an infinite composition of bijections always a bijection? Also, a function iteration notation question.
  • Are story points really a good measure for velocity?
  • Tips/strategies to managing my debt
  • Solar System Replacement?
  • When are these base spaces isomorphic?
  • Washing machine drain
  • What happens if your child sells your car?
  • Do academic researchers generally not worry about their work infringing on patents? Have there been cases where they wish they had?
  • Polynomial isoperimetric inequalities for finitely presented subdirect products of limit groups
  • If it's true that a reservation fee for a cruise ship is non-refundable, then what happens if somebody cancels?
  • Combinatorial type construction of the Free Operad
  • Make a GCSE student's error work
  • A finance broker made me the primary instead of a co-signer
  • Why is the completely dark disk of the Moon visible on a new moon if the lunar orbit is at an angle to the Earth’s?
  • Why, fundamentally, does adding sin graphs together always produce another sin graph?
  • Pass ethernet directly to VM and use WiFi for OS
  • Fantasy book in which a joker wonders what's at the top of a stone column
  • What are these red pointy flower buds with heart-shaped leaves?
  • Splitting a Number into Random Parts
  • Search values by priority in stream
  • "Continuity" in a metric space

variable assignment in jinja2

COMMENTS

  1. python

    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 = {{

  2. How do I assign a jinja2 variable value to use later in template?

    More information about assignments in jinja2 here. Or simply do the conditionals within python and pass the result to jinja2 template:

  3. Jinja2 Tutorial

    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 ...

  4. Template Designer Documentation

    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.

  5. # Creating new Jinja2 variables

    Learn how to create and use new Jinja2 variables in your Flask templates. Follow the step-by-step guide and code examples.

  6. How to Use the Jinja Template Engine in Python + Flask

    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.

  7. Setting Variables in Jinja Templates: A Guide to Python 3 Programming

    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.

  8. Jinja2: Using Set Variable Block

    This article explores the usage of the set variable block in Jinja2 templates. Learn how to assign and modify values using this feature.

  9. Variables and Jinja2 Templates

    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.

  10. Jinja2 Tutorial

    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!

  11. SaltStack: Setting a jinja2 variable from an inner block scope

    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.

  12. Debugging Jinja2: Resolving Common Issues with Variables in {% if

    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 ...

  13. About variable overriding behavior of Jinja2

    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.

  14. Use lookup/dynamic variable names in Ansible jinja2 template

    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...

  15. Block assignment with {% set %}...{% endset %} · Issue #232 · pallets/jinja

    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.

  16. How to render variables within the static path in jinja templates?

    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.

  17. Namespaces do not allow multi-variable assignments #1413

    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.

  18. Using variables in the Jinja2 template in ansible Playbook

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