askama
askama copied to clipboard
Compilation error when including template that contains block
When I try to include a template that contains a block definition from another template, I get the error below.
use askama::Template;
#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate<'a> {
name: &'a str,
}
fn main() {
let hello = IndexTemplate { name: "world" };
println!("{}", hello.render().unwrap());
}
index.html
{% include "hello.html" %}
hello.html
{% block foo %}{% endblock %}
Hello, {{ name }}!
Output
error: no block ancestors available
--> src/main.rs:3:10
|
3 | #[derive(Template)]
| ^^^^^^^^
|
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no method named `render` found for struct `IndexTemplate` in the current scope
--> src/main.rs:11:26
|
5 | struct IndexTemplate<'a> {
| ------------------------ method `render` not found for this
...
11 | println!("{}", hello.render().unwrap());
| ^^^^^^ method not found in `IndexTemplate<'_>`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `render`, perhaps you need to implement it:
candidate #1: `Template`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `askama-test` due to 2 previous errors
You wrote {% include %} when you wanted to use {% extends %}: https://djc.github.io/askama/template_syntax.html#template-inheritance
{% include %} in Askama is just like #include in C: The source of the included file gets "pasted" into the including file. The error tells you that cannot use {% block %} without {% extends %}. But, yeah, the error message could be better.
No I actually want it to be included in this case. In a more advanced example I would include the hello.html template in multiple other templates and have other templates extend from hello.html and implement the foo block.
You are describing exactly what {% extends %} does. Maybe Jinja2's readme is more clear to you? https://jinja2docs.readthedocs.io/en/stable/templates.html#template-inheritance
Hmm... I'm still not entirely convinced that {% include %} is the wrong choice here for me but let's say I go with {% extends %} instead. How would you solve the following then?
I still have the same main.rs but the following templates to better illustrate my problem:
index.html
<div>
<h1>Welcome</h1>
{% include "hello_foo.html" %}
</div>
hello_base.html
<div>
<p>Below me is the header</p>
{% block header %}{% endblock %}
<p>Above me is the header</p>
</div>
Hello, {{ name }}!
hello_foo.html
{% extends "hello_base.html" %}
{% block header %}foo{% endblock %}
Because with this I get another error:
error: extend blocks only allowed at the top level
--> src/main.rs:3:10
|
3 | #[derive(Template)]
| ^^^^^^^^
|
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no method named `render` found for struct `IndexTemplate` in the current scope
--> src/main.rs:11:26
|
5 | struct IndexTemplate<'a> {
| ------------------------ method `render` not found for this
...
11 | println!("{}", hello.render().unwrap());
| ^^^^^^ method not found in `IndexTemplate<'_>`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `render`, perhaps you need to implement it:
candidate #1: `Template`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `askama-test` due to 2 previous errors
Testing the exact same templates with Jinja2 (version 3.0.3) works as expected and generates the correct output:
main.py
from jinja2 import Environment, FileSystemLoader, select_autoescape
env = Environment(
loader=FileSystemLoader("templates"),
autoescape=select_autoescape()
)
template = env.get_template("index.html")
print(template.render(name="world"))
Output (with manual fix to indentation fixes for better visualization)
<div>
<h1>Welcome</h1>
<div>
<p>Below me is the header</p>
foo
<p>Above me is the header</p>
</div>
Hello, world!
</div>
Seems like I've landed at the same limitation as described in https://github.com/djc/askama/issues/572
I don't know why this restriction exists. Maybe you could comment out https://github.com/djc/askama/blob/0b376b439f759613966916787b613616627bb3f9/askama_shared/src/generator.rs#L445-L447 and tell us what works and what breaks then?
Then I get the first error again (because of the {% include "hello_foo.html" %} in index.html):
error: no block ancestors available
--> src/main.rs:3:10
|
3 | #[derive(Template)]
| ^^^^^^^^
|
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no method named `render` found for struct `IndexTemplate` in the current scope
--> src/main.rs:11:26
|
5 | struct IndexTemplate<'a> {
| ------------------------ method `render` not found for this
...
11 | println!("{}", hello.render().unwrap());
| ^^^^^^ method not found in `IndexTemplate<'_>`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `render`, perhaps you need to implement it:
candidate #1: `Template`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `askama-test` due to 2 previous errors