title: Using StreamField contents programmatically from withing the Page get_context function
body: <p>I have been trying to learn Wagtail and the intricacies of using <code>StreamField</code>s and blocks are giving me a headache. I had no problems following the Wagtail docs and the demo app, but going beyond that seems to be insurmountable without external help.</p>
  <p>Here is what I am trying (and failing) to achieve.</p>
  <p>When playing around with the Blog application, I tried to extend it so the <code>StreamField</code> allows for adding of code blocks with syntax highlighting, based on <em>pygments</em>. The source code is managed by a custom <code>StructBlock</code> class (<code>CodeBlock</code>, naturally) and is part of the <code>StreamField</code> body of the <code>BlogPage</code>. In Wagtail admin I can enter code, used language, what highlight style to apply and whether to show line numbers or not. This all works perfectly fine, up to the point where I would like to select the additional stylesheet for the rendering template based on the selected highlight style. Here is how the page template would include the stylesheet:</p>
  <pre class="lang-python prettyprint-override"><code>{% block extra_css %}
      {# This goes in the page &lt;head&gt; section #}
      {% if has_code_block %}
          {% if code_colorizer %}
              &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{% static 'css/highlight_{{ code_colorizer }}.css' %}&quot;&gt;
          {% else %}
              &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{% static 'css/highlight_default.css' %}&quot;&gt;
          {% endif %}
      {% endif %}
  {% endblock %}
  </code></pre>
  <p>The <code>CodeBlock</code> does its job in the render method (idea gratefully found - and shamelessly used - online). At this point in the app flow it's too late to add the highlight style to the page context, so I tried to decompose the page body field in an overridden def get_context function, without success. I just haven't been able to get to the underlying JSON text or access the data through any of the class members from withing the <code>BlogPage</code> class.</p>
  <p><strong>Is there a way to add the highlight style to the page context just after the data is loaded from the DB and before given over to the template?</strong></p>
  <p>Here is my basic blog page:</p>
  
  <pre class="lang-python prettyprint-override"><code>class BlogPage(Page):
      tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
      posted_date = models.DateField(&quot;Post date&quot;)
      edited_date = models.DateField(&quot;Edited date&quot;, null=True, blank=True)
      feed_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+')
      body = StreamField(BlogStreamBlock)
  
      search_fields = Page.search_fields + [
          index.SearchField('body')
      ]
  
      subpage_types = []
  
      parent_page_types = ['BlogIndexPage']
  
      @property
      def blog_index(self):
          return self.get_ancestors().type(BlogIndexPage).last()
  
  BlogPage.content_panels = [
      FieldPanel('title', classname='full title'),
      FieldPanel('posted_date'),
      FieldPanel('edited_date'),
      StreamFieldPanel('body'),
      InlinePanel('related_links', label=&quot;Related links&quot;),
  ]
  
  BlogPage.promote_panels = Page.promote_panels + [
      ImageChooserPanel('feed_image'),
      FieldPanel('tags'),
  ]
  </code></pre>
  <p>This is the definition of my <code>BlogStreamBlock</code> class:</p>
  <pre class="lang-python prettyprint-override"><code>class BlogStreamBlock(StreamBlock):
      subtitle = CharBlock(icon='title', classname='title')
      abstract = RichTextBlock(icon='pilcrow')
      paragraph = RichTextBlock()
      aligned_image = ImageBlock()
      source_code = CodeBlock()
      quote = QuoteBlock()
  </code></pre>
  <p>And finally, here is the <code>CodeBlock</code> class:</p>
  <pre class="lang-python prettyprint-override"><code>class CodeBlock(StructBlock):
      LANGUAGE_CHOICES = (
          ('aspx-cs', '.NET ASP/C#'),
          ('aspx-vb', '.NET ASP/VisualBasic'),
          ('csharp', '.NET C#'),
          ('fsharp', '.NET F#'),
          ('vbnet', '.NET VisualBasic'),
          ('ng2', 'Angular 2'),
          ('html+ng2', 'Angular 2 Html'),
          ('apache', 'Apache Config'),
          ('arduino', 'Arduino Sketch'),
          ('asm', 'Assembly'),
          ('bash', 'Bash Shell'),
          ('batch', 'Batch CMD File'),
          ('c', 'C'),
          ('cpp', 'C++'),
          ('cmake', 'CMake'),
          ('coffeescript', 'Coffee Script'),
          ('css', 'CSS'),
          # ... and many, many more ...
          ('vhdl', 'Vhdl'),
          ('registry', 'Windows Registry'),
          ('xml', 'XML'),
          ('xml+php', 'XML/PHP'),
          ('xslt', 'XSLT'),
          ('yaml', 'Yaml'),
      )
  
      COLORIZER_CHOICES = (
          ('abap', 'Abap'),
          ('algol', 'Algol'),
          ('algol_nu', 'Algol Nu'),
          # ... finish the list with all the highlight styles in the current version of pygments
          ('vs', 'Vs'),
          ('xcode', 'Xcode'),
      )
  
      language = ChoiceBlock(choices=LANGUAGE_CHOICES, classname='full')
      colors = ChoiceBlock(choices=COLORIZER_CHOICES, classname='full')
      code = TextBlock()
      line_numbers = BooleanBlock(classname='full')
  
      class Meta:
          icon = 'code'
  
      def render(self, value, context=None):
          src = value['code'].strip('\n');
          lang = value['language']
          line_nos = value['line_numbers']
  
          lexer = get_lexer_by_name(lang)
          formatter = get_formatter_by_name('html', linenos='table' if line_nos else False, cssclass='codehilite', style='default',noclasses=False)
          return mark_safe(highlight(src, lexer, formatter))
  </code></pre>