benjarwar benjarwar - 3 months ago 14
CSS Question

Wagtail/Django block doesn't render content properly from custom/nested StructBlock template

I have a block in the head of my base template that will render "extra" CSS. This CSS will be customized from fields coming in from a Wagtail CMS instance.

So, in the

base.html
template I have:

<head>
{% block extra_css %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>


Then, in my
detail.html
template, which extends off of the base, I have:

{% block content %}
{% for block in page.body %}
{{ block }}
{% endfor %}
{% endblock %}


body
is a
StreamField
in Wagtail. One of said fields is a custom
StructBlock
, the model of which is set up like so:

class CalloutBlock(blocks.StructBlock):
accent_color = blocks.CharBlock(required=False, label='Accent Color', help_text='HEX Value/Color')
class Meta:
template = 'inc/blocks/callout.inc.tpl'


Finally, in that
callout.inc.tpl
template, I am attempting to render a
<style>
tag that should get injected in my
extra_css
block:

{% block extra_css %}
<style>
.accent_color {
background-color: {{accent_color}} !important;
}
</style>
{% endblock %}


However, this block is not injected into the
<head>
as I'd expected. Instead, it renders in the body, like so, as if the
{% block extra_css %}
tag were not there at all:

<head>
</head>
<body>
<style>
.accent_color {
background-color: {{accent_color}} !important;
}
</style>
</body>


Is simply a limitation in Django templates? Is nesting the issue? Or is it because I'm using a custom template at the model level, and that's somehow outside the scope of the parent template parsing?

Django: 1.10

Wagtail: 1.6

Answer

This is a limitation in the way custom templates for StreamField blocks work. (There's a similar limitation in Django templating in general too, though - the {% block %} mechanism only works in conjunction with {% extends %}, not {% include %}.) The HTML content for the block is rendered in a separate call to the template engine, independently of the outer page template, so there's no way of passing control between the two.

(Note that Wagtail 1.6 introduces the {% include_block %} tag, which improves the situation a bit by making it possible to pass variables from the outer template's context to the block template. It still won't allow passing control from one to the other, though.)