diff --git a/docs/topics/streamfield.rst b/docs/topics/streamfield.rst index 185f9c90fa..dfce70fe09 100644 --- a/docs/topics/streamfield.rst +++ b/docs/topics/streamfield.rst @@ -442,6 +442,28 @@ Within the template, the block value is accessible as the variable ``value``: The line ``value.bound_blocks.biography.render`` warrants further explanation. While blocks such as RichTextBlock are aware of their own rendering, the actual block *values* (as returned when accessing properties of a StructBlock, such as ``value.biography``), are just plain Python values such as strings. To access the block's proper HTML rendering, you must retrieve the 'bound block' - an object which has access to both the rendering method and the value - via the ``bound_blocks`` property. +To pass additional context variables to the template, block subclasses can override the ``get_context`` method: + +.. code-block:: python + + import datetime + + class EventBlock(blocks.StructBlock): + title = blocks.CharBlock(required=True) + date = blocks.DateBlock(required=True) + + def get_context(self, value): + context = super(EventBlock, self).get_context(value) + context['is_happening_today'] = (value['date'] == datetime.date.today()) + return context + + class Meta: + template = 'myapp/blocks/event.html' + + +In this example, the variable ``is_happening_today`` will be made available within the block template. + + Custom block types ------------------ diff --git a/wagtail/tests/testapp/blocks.py b/wagtail/tests/testapp/blocks.py new file mode 100644 index 0000000000..c598e6bc71 --- /dev/null +++ b/wagtail/tests/testapp/blocks.py @@ -0,0 +1,14 @@ +from wagtail.wagtailcore import blocks + + +class LinkBlock(blocks.StructBlock): + title = blocks.CharBlock() + url = blocks.URLBlock() + + def get_context(self, value): + context = super(LinkBlock, self).get_context(value) + context['classname'] = 'important' if value['title'] == 'Torchbox' else 'normal' + return context + + class Meta: + template = 'tests/blocks/link_block.html' diff --git a/wagtail/tests/testapp/templates/tests/blocks/link_block.html b/wagtail/tests/testapp/templates/tests/blocks/link_block.html new file mode 100644 index 0000000000..8e3f4b27a9 --- /dev/null +++ b/wagtail/tests/testapp/templates/tests/blocks/link_block.html @@ -0,0 +1 @@ +{{ self.title }} \ No newline at end of file diff --git a/wagtail/wagtailcore/blocks/base.py b/wagtail/wagtailcore/blocks/base.py index ba483c309d..913c07510f 100644 --- a/wagtail/wagtailcore/blocks/base.py +++ b/wagtail/wagtailcore/blocks/base.py @@ -200,6 +200,12 @@ class Block(six.with_metaclass(BaseBlock, object)): """ return value + def get_context(self, value): + return { + 'self': value, + self.TEMPLATE_VAR: value, + } + def render(self, value): """ Return a text rendering of 'value', suitable for display on templates. By default, this will @@ -208,10 +214,7 @@ class Block(six.with_metaclass(BaseBlock, object)): """ template = getattr(self.meta, 'template', None) if template: - return render_to_string(template, { - 'self': value, - self.TEMPLATE_VAR: value, - }) + return render_to_string(template, self.get_context(value)) else: return self.render_basic(value) diff --git a/wagtail/wagtailcore/tests/test_blocks.py b/wagtail/wagtailcore/tests/test_blocks.py index 93bcb30d80..f7b54441b1 100644 --- a/wagtail/wagtailcore/tests/test_blocks.py +++ b/wagtail/wagtailcore/tests/test_blocks.py @@ -1439,3 +1439,14 @@ class TestSystemCheck(TestCase): self.assertEqual(errors[1].id, 'wagtailcore.E001') self.assertEqual(errors[1].hint, "Block names cannot contain spaces") self.assertEqual(errors[0].obj, failing_block_2) + + +class TestTemplateRendering(TestCase): + def test_render_with_custom_context(self): + from wagtail.tests.testapp.blocks import LinkBlock + + block = LinkBlock() + value = block.to_python({'title': 'Torchbox', 'url': 'http://torchbox.com/'}) + result = block.render(value) + + self.assertEqual(result, 'Torchbox')