Opened 10 years ago
Closed 10 years ago
#23591 closed Uncategorized (needsinfo)
RFC: Shared parser-level context to all templates involved in output
Reported by: | Anton Stoychev | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | 1.7 |
Severity: | Normal | Keywords: | template, parser, output, context |
Cc: | Aymeric Augustin | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I've spend a few days thinking of a better way to defined assets (css and javascripts) in templates and partials. This is what I came across and what I came up with.
Problem
Django templates have the ability to extend
and include
other templates. So a full HTML
(or other format) output can consist of rendering several templates, which could have been extended or included.
However, each template is rendered separately and is not aware that in the current output there would be other templates involved.
In the case of extended templates the only thing shared is the rendering context
(variables, etc) but still there isn’t awareness that other templates are also rendered to make the complete output.
Now, this “awareness” sounds like we should sacrifice encapsulation, but there is a solution which in fact improves encapsulation.
Don’t think this is aiming “all templates must share context with variables and other info”. It’s not about this. We must, however, enable templates to say “hey, i need this and this, and i’m rendering that and that, account for me”. This improves encapsulation.
Common scenario
You are outputting HTML
. You have a base template like layout.html
and other templates like home.html
. The template home.html
also includes _nav.html
and _footer.html
.
Now, _footer.html
and _nav.html
have some cool animations going on. So they need certain CSS
and JavaScript
files. Right now in Django, you can’t defined these in the _footer.html
and _nav.html
and be outputted in the end of layout.html
because included templates neither share context, nor can influence block
tags.
So you end up defining the required CSS
and JavaScript
for the partials in either home.html
or layout.html
. This way you already make home.html
and layout.html
aware of the partials and if partials change, home.html
and layout.html
should also change. That is not good encapuslation.
Proposed Solution
Django templates are rendered on 2 levels:
- parser level rendering (compile template to DOM-like structure)
- context level rendering (with context and variables)
We aim better encapsulation so let limit ourselves to parser level. This is the lower level rendering where we only see template nodes and no variables - something like DOM.
I've seen a similar approach to attach __loaded_blocks
attribute to the parser object when dealing with block
tag.
I've played around and I made a package (django-ouput-context) that implements this. It adds a parser-level context that is shared with all templates involved in making the complete output (extended and included).
The context is attached to the tempalte parser
which is passed to django tags registed via @register.tag('yourtag')
so you can now write your own tags that make use of this context to communicate template requirements or planned structure.
How it does this?
It overrides include
and extend
template tags.
However there’s a lot of code duplicated from django codebase and this is ugly.
It’s because the only thing that django_output_context
do is to add a output_context
parameter to all calls that start from include
and extend
tags down to the compile_string
function that creates the parser.
Do you think something like this is worth including in Django?
Alternatively, do you know of a simpler approach than to override so much calls and therefore so much code?
Change History (4)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
Cc: | added |
---|
Aymeric, maybe you'd like to offer an opinion on this based on your template refactor research?
comment:3 by , 10 years ago
The topic discussed here is orthogonal to my project.
I don't know enough about the internals of Django templates to comment on the proposal.
AFAICT this is the same problem that https://github.com/ojii/django-sekizai attempts to solve.
comment:4 by , 10 years ago
Resolution: | → needsinfo |
---|---|
Status: | new → closed |
Closing as "needs info" until the required discussion takes place on the mailing list and there is a consensus if we want to make a change in Django itself.
This type of proposal is better suited to the DevelopersMailingList where it'll reach a broader audience. I'd suggest to post it there.