Skip to content
New issue

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

{% block <name> required %} #1147

Closed
ddevault opened this issue Feb 6, 2020 · 11 comments · Fixed by #1233
Closed

{% block <name> required %} #1147

ddevault opened this issue Feb 6, 2020 · 11 comments · Fixed by #1233
Milestone

Comments

@ddevault
Copy link

ddevault commented Feb 6, 2020

This is a feature request for blocks which are required to be implemented by the leaf template. One example of where this would be useful is in title blocks. In the parent template:

{% block title required %}{% endblock %}

And in the child:

{% extends "example.html" %}
{% block title %}
<title>My Page</title>
{% endblock %}

If the title block is not present in the latter, an error is rased. If the block has any contents other than whitespace or comments in the former, an error is raised. In effect, this requires all pages to have titles.

@davidism
Copy link
Member

Should this require output or just that there is some expression present? For example, {% if var %} would require a runtime check to ensure it actually output something.

@ddevault
Copy link
Author

Just that the block is present, it can be empty. The goal is to make the programmer acknowledge that this block is required. If they know better and think it should be empty, then by all means.

@septatrix
Copy link
Contributor

You can archive something similar by capturing the block content using a set/endset block and then testing if the variable is empty - if it is you could throw an error.

Nevertheless I think this would be a great addition as the hack above does neither allow empty block nor proper exceptions.

@juped
Copy link

juped commented Jun 9, 2020

@amy-lei and @ovezovs will be working on this!

@davidism
Copy link
Member

Some notes from discussion with @amy-lei.

A required block must be overridden at some point, but not necessarily the direct child. Basically, if a block has required, it should fail at runtime if it's rendered directly. For example, if c extends b extends a, and a has a required block, then b or c must override the block if c is rendered.

This possibly requires adding some tracking information to the context to know what block is being rendered by what template. Some code will need to be added when compiling the block functions to check the context to see if they are required and raise an error if so.

Fairly sure this has to be a runtime error, at compile time we don't know enough information. extends can take a variable for the template name, or be wrapped in an if block, and the compiler only sees the current template, not the (potential) parent template and its blocks.

Open questions that don't have to be solved right now:

  • What happens if a template with a required block is rendered directly, rather than extended? With the implementation above, this would fail.
  • Related, what happens if a child template overrides a required block, but also marks it as required? This could be interpreted as "use this if the template is rendered directly, but require templates extending it to override the block". Again, with the implementation above, this would fail.

@ddevault
Copy link
Author

I think it would be fair to say that the terminal template (the tail, if you prefer) must not have any required blocks, and each required block anywhere in the tree must be implemented by exactly one descendant. This should address both open questions.

@amy-lei
Copy link
Contributor

amy-lei commented Jun 12, 2020

each required block anywhere in the tree must be implemented by exactly one descendant

Following David's example, does this mean that if both b and c override the required block and c is the rendered template, an error should be raised?

@ddevault
Copy link
Author

Eh, maybe not. Perhaps the rule should be that at least one descendant must implement it, and the bottom-most implementation wins. That would map most closely to the behavior of non-required blocks.

@ddevault
Copy link
Author

Does that seem right?

@davidism
Copy link
Member

Yeah, that's basically what will happen if we don't address them at all right now. If a required block is rendered directly for any reason, it fails.

I don't think we should do the "override exactly once" check, if it's possible to do at all. A child of a child could legitimately want to further override a block, such as adding some information then calling super().

@ddevault
Copy link
Author

Thanks Amy!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants