Placeholder content
{% endblock %}# Template Syntax ## Variables Top-level template variables are defined by the template's context type. You can use a dot (`.`) to access variable's attributes or methods. Reading from variables is subject to the usual borrowing policies. For example, `{{ name }}` will get the ``name`` field from the template context, while `{{ user.name }}` will get the ``name`` field of the ``user`` field from the template context. ## Using constants in templates You can use constants defined in your Rust code. For example if you have: ```rust pub const MAX_NB_USERS: usize = 2; ``` defined in your crate root, you can then use it in your templates by using ``crate::MAX_NB_USERS``: ```jinja
The user limit is {{ crate::MAX_NB_USERS }}.
{% set value = 4 %} {% if value > crate::MAX_NB_USERS %}{{ value }} is bigger than MAX_NB_USERS.
{% else %}{{ value }} is less than MAX_NB_USERS.
{% endif %} ``` ## Assignments Inside code blocks, you can also declare variables or assign values to variables. Assignments can't be imported by other templates. Assignments use the `let` tag: ```jinja {% let name = user.name %} {% let len = name.len() %} {% let val -%} {% if len == 0 -%} {% let val = "foo" -%} {% else -%} {% let val = name -%} {% endif -%} {{ val }} ``` Like Rust, Askama also supports shadowing variables. ```jinja {% let foo = "bar" %} {{ foo }} {% let foo = "baz" %} {{ foo }} ``` For compatibility with Jinja, `set` can be used in place of `let`. ## Filters Values such as those obtained from variables can be post-processed using **filters**. Filters are applied to values using the pipe symbol (`|`) and may have optional extra arguments in parentheses. Filters can be chained, in which case the output from one filter is passed to the next. For example, `{{ "{:?}"|format(name|escape) }}` will escape HTML characters from the value obtained by accessing the `name` field, and print the resulting string as a Rust literal. The built-in filters are documented as part of the [filters documentation](filters.md). To define your own filters, simply have a module named `filters` in scope of the context deriving a `Template` `impl`. Note that in case of name collision, the built in filters take precedence. ## Whitespace control Askama considers all tabs, spaces, newlines and carriage returns to be whitespace. By default, it preserves all whitespace in template code, except that a single trailing newline character is suppressed. However, whitespace before and after expression and block delimiters can be suppressed by writing a minus sign directly following a start delimiter or leading into an end delimiter. Here is an example: ```text {% if foo %} {{- bar -}} {% else if -%} nothing {%- endif %} ``` This discards all whitespace inside the if/else block. If a literal (any part of the template not surrounded by `{% %}` or `{{ }}`) includes only whitespace, whitespace suppression on either side will completely suppress that literal content. If the whitespace default control is set to "suppress" and you want to preserve whitespace characters on one side of a block or of an expression, you need to use `+`. Example: ```text text ``` In the above example, one whitespace character is kept between the `href` and the `class` attributes. There is a third possibility. In case you want to suppress all whitespace characters except one (`"minimize"`), you can use `~`: ```jinja {% if something ~%} Hello {%~ endif %} ``` To be noted, if one of the trimmed characters is a newline, then the only character remaining will be a newline. Whitespace controls can also be defined by a [configuration file](configuration.md) or in the derive macro. These definitions follow the global-to-local preference: 1. Inline (`-`, `+`, `~`) 2. Derive (`#[template(whitespace = "suppress")]`) 3. Configuration (in `askama.toml`, `whitespace = "preserve"`) Two inline whitespace controls may point to the same whitespace span. In this case, they are resolved by the following preference. 1. Suppress (`-`) 2. Minimize (`~`) 3. Preserve (`+`) ## Functions There are several ways that functions can be called within templates, depending on where the function definition resides. These are: - Template `struct` fields - Static functions - Struct/Trait implementations ### Template struct field When the function is a field of the template struct, we can simply call it by invoking the name of the field, followed by parentheses containing any required arguments. For example, we can invoke the function `foo` for the following `MyTemplate` struct: ```rust #[derive(Template)] #[template(source = "{{ foo(123) }}", ext = "txt")] struct MyTemplate { foo: fn(u32) -> String, } ``` However, since we'll need to define this function every time we create an instance of `MyTemplate`, it's probably not the most ideal way to associate some behaviour for our template. ### Static functions When a function exists within the same Rust module as the template definition, we can invoke it using the `self` path prefix, where `self` represents the scope of the module in which the template struct resides. For example, here we call the function `foo` by writing `self::foo(123)` within the `MyTemplate` struct source: ```rust fn foo(val: u32) -> String { format!("{}", val) } #[derive(Template)] #[template(source = "{{ self::foo(123) }}", ext = "txt")] struct MyTemplate; ``` This has the advantage of being able to share functionality across multiple templates, without needing to expose the function publicly outside of its module. However, we are not limited to local functions defined within the same module. We can call _any_ public function by specifying the full path to that function within the template source. For example, given a utilities module such as: ```rust // src/templates/utils/mod.rs pub fn foo(val: u32) -> String { format!("{}", val) } ``` Within our `MyTemplate` source, we can call the `foo` function by writing: ```rust // src/templates/my_template.rs #[derive(Template)] #[template(source = "{{ crate::templates::utils::foo(123) }}", ext = "txt")] struct MyTemplate; ``` ### Struct / trait implementations Finally, we can invoke functions that are implementation methods of our template struct, by referencing `Self` (note the uppercase `S`) as the path, before calling our function: ```rust #[derive(Template)] #[template(source = "{{ Self::foo(self, 123) }}", ext = "txt")] struct MyTemplate { count: u32, }; impl MyTemplate { fn foo(&self, val: u32) -> String { format!("{} is the count, {} is the value", self.count, val) } } ``` If the implemented method requires a reference to the struct itself, such as is demonstrated in the above example, we can pass `self` (note the lowercase `s`) as the first argument. Similarly, using the `Self` path, we can also call any method belonging to a trait that has been implemented for our template struct: ```rust trait Hello { fn greet(name: &str) -> String; } #[derive(Template)] #[template(source = r#"{{ Self::greet("world") }}"#, ext = "txt")] struct MyTemplate; impl Hello for MyTemplate { fn greet(name: &str) -> String { format!("Hello {}", name) } } ``` ## Template inheritance Template inheritance allows you to build a base template with common elements that can be shared by all inheriting templates. A base template defines **blocks** that child templates can override. ### Base template ```htmlPlaceholder content
{% endblock %}Placeholder content
{% endblock content %} ``` ### Child template Here's an example child template: ```html {% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {% endblock %} {% block content %}Hello, world!
{% call super() %} {% endblock %} ``` The `extends` tag tells the code generator that this template inherits from another template. It will search for the base template relative to itself before looking relative to the template base directory. It will render the top-level content from the base template, and substitute blocks from the base template with those from the child template. Inside a block in a child template, the `super()` macro can be called to render the parent block's contents. ## HTML escaping Askama by default escapes variables if it thinks it is rendering HTML content. It infers the escaping context from the extension of template filenames, escaping by default if the extension is one of `html`, `htm`, or `xml`. When specifying a template as `source` in an attribute, the `ext` attribute parameter must be used to specify a type. Additionally, you can specify an escape mode explicitly for your template by setting the `escape` attribute parameter value (to `none` or `html`). Askama escapes `<`, `>`, `&`, `"`, and `'`, according to the [OWASP escaping recommendations][owasp]. Use the `safe` filter to prevent escaping for a single expression, or the `escape` (or `e`) filter to escape a single expression in an unescaped context. [owasp]: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-for-html-contexts ```rust #[derive(Template)] #[template(source = "{{strvar}}")] struct TestTemplate { strvar: String, } fn main() { let s = TestTemplate { strvar: "// my is \"unsafe\" & should be 'escaped'".to_string(), }; assert_eq!( s.render().unwrap(), "// my <html> is "unsafe" & \ should be 'escaped'" ); } ``` ## Control structures ### For Loop over each item in an iterator. For example: ```html{{arg}}
{% endmacro heading %} ``` You can also specify arguments by their name (as defined in the macro): ```jinja {% macro heading(arg, bold) %}