-
Notifications
You must be signed in to change notification settings - Fork 16
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
Parent macros are not available when rendering individual blocks #21
Comments
Fixed by #30 . |
Hi @sponsfreixes - after doing more work on my own application, I'm discovering that the initial solution for this may in fact break a lot of other things. At this point, I'm not entirely sure what the path forward is, but I'm still researching. I was very excited to get this part working since I had an immediate use for it, but now I'm finding that both of these PRs I made probably need to be reverted. (#30 & #33) While this works for the simple template cases, more complex templates cause grief because (afaict) the only way to get jinja2 to generate the macros is to call More concretely:
calling Prior to my PR, that would have rendered the I've spent several hours trying to figure out a way around this new discovery and haven't gotten anywhere meaningful. I apologize for not finding this earlier and wasting everyone's time. I believe getting macros to work will be very beneficial, but not at the expense of what should be basic/original functionality. |
Well that's unfortunate. Than you very for all the work and time you have
put into it!
I'd say the plan is for me to revert these changes and publish a stable
version to PyPI. After that, I will definitely extend the test suite to
cover more complex cases like the ones you describe. And after that, with
whatever time we need, we try to figure out the macros.
Unfortunately , I won't have access to my development PC until Saturday, so
we will have to wait until then.
|
I definitely agree with reverting. I've been playing some more and have come up with a thought, but requires a modification to the render_block calls def render_block(
environment: Environment,
template_name: str,
block_name: str,
shared: bool = False, # added for completeness [1]
locals: t.Optional[t.Mapping[str, t.Any]] = None, # added for usefulness [1]
*args: typing.Any,
**kwargs: typing.Any,
) -> str: same for and then later: With that mechanism in place, the user is free to inject whatever they want into the locals, including macros. Which puts the onus on them to properly load the macros. An example can be documented and also state that the template should only have macros in it and not other template content. def get_jinja_macros(template_name):
template = current_app.jinja_env.get_or_select_template(template_name) # flask specific
template_module = template.module
macros = {
m: getattr(template_module, m)
for m in dir(template_module)
if isinstance(getattr(template_module, m), Macro)
}
return macros
...
macros = get_jinja_macros("mymacros.jinja2")
render_template("main.html.jinja2", "content_block", locals=macros, myvar="something")
... [1] - it's possible if a user has existing code with variables named |
It introduced a bug that breaks some complex templates. The templates of our test suite are too simple to be impacted by the bug, so we missed it. See comments on Issue #30: #21 (comment)
A new version (1.5.0) has been pushed reverting the changes. I'll give some thought to your proposal, I'm OK with being a feature where the users need to know that there are some caveats associated with it. |
I'll work up a PR based off of 1.5.0 for what I've put together that is working for me and we can move implementation discussion there. I think at the least, those jinja2 variables (shared/locals) should be exposed to the user when rendering fragments. |
Welp, I have made a discovery that I should have realized earlier. This works (for flask): macros = get_jinja_macros("macros.html.jinj2")
return render_block("template.html.jinja2", "content", **macros, var1="thing", var2=2, ...) In this case, the loaded |
This is a great finding! Something similar will probably be possible for other frameworks. What's |
def get_jinja_macros(template_name):
template = current_app.jinja_env.get_or_select_template(template_name) # flask specific
template_module = template.module # [1]
macros = {
m: getattr(template_module, m)
for m in dir(template_module)
if isinstance(getattr(template_module, m), Macro)
}
return macros [1] for async usage, you have to call a different method ( |
Is anyone using macros in the same file just for readability? The above template.module crash in this case asking for a context variable (in my case a FastApi request) {% macro func(a) %}
<td>
...long verbose body, but specific to this template only...
</td>
{% endmacro %}
{{ func(global_variable) }}
{% block block_one %}
{{ func(variable_1) }}
{% endblock %}
{% block block_two %}
{{ func(variable_2) }}
{% endblock %} Edit: leaving this here in case anyone else is curious. |
It would be a super cool feature if, in case of block-rendering, parent level macro imports were available for the blocks. For now, we either cannot use macros within blocks, which is very restricting, or need to import the macros in the blocks as well, which is uncomfortable and unintuitive. The worst part of it, is that one can never now for sure, without testing, if all block-rendering would work even if the complete template renders.
Desired syntax:
Current workaround:
The text was updated successfully, but these errors were encountered: