pythondjangowagtailwagtail-streamfieldwagtail-snippet

Wagtail SnippetChooserBlock in Streamfield


I am having some trouble getting the values from a snippet, that I have included into a streamfield using a Snippet Chooser Block.

BioSnippet:

@register_snippet
class BioSnippet(models.Model):
    name = models.CharField(max_length=200, null=True)
    job_title = models.CharField(max_length=200, null=True, blank=True)
    bio = RichTextField(blank=True)
    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Bio Image'
    )
    contact_email = models.CharField(max_length=50, null=True, blank=True)
    contact_phone = models.CharField(max_length=50, null=True, blank=True)

    panels = [
        FieldPanel('name'),
        FieldPanel('job_title'),
        FieldPanel('bio'),
        ImageChooserPanel('image'),
        FieldPanel('contact_email'),
        FieldPanel('contact_phone'),
    ]

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name',]

Bio Streamfield Definitions:

class BioInline(StructBlock):
    bio = SnippetChooserBlock(BioSnippet)

class BioBlock(StructBlock):
    overall_title = CharBlock(required=False)
    bios = ListBlock(BioInline())

This all works, but when I get to the template, I cannot seem to access the values of the snippet

{% for b in child.value.bios %}
    {{ b }}

    <hr>
    {{ b.name }}

{% endfor %}

the {{ b }} tag outputs:

bio
Sales Team

However {{ b.name }} outputs nothing. Neither does {{ b.values.name }} or any other permutation I can guess at. I suspect the values are just not being pulled down.


Solution

  • bios here is defined as a list of BioInline values, and so b in your template would be a BioInline value - which has a single property, bio (giving you the actual BioSnippet object). To get the name, you'd therefore have to use: {{ b.bio.name }}.

    I don't think the BioInline object is actually gaining you anything though - you could instead define BioBlock as:

    class BioBlock(StructBlock):
        overall_title = CharBlock(required=False)
        bios = ListBlock(SnippetChooserBlock(BioSnippet))
    

    which would make bios a list of BioSnippets - {{ b.name }} would then work as expected.