Search code examples
tagswagtail

Wagtail: Rendering tags from Fieldblock


I am really stuck on this: (sorry, newbie problems) Following the method exposed in this post I need to render the tags in a page, but I am not able to get the tag values through the @property

The code is as follow, the models:

class TagsBlock(blocks.FieldBlock):
    """
    Basic Stream Block that will use the Wagtail tags system.
    Stores the tags as simple strings only.
    """

    def __init__(self, required=False, help_text=None, **kwargs):
        # note - required=False is important if you are adding this tag to an existing streamfield
        self.field = forms.CharField(widget=AdminTagWidget, required=False)
        super().__init__(**kwargs)
  

class ServicesPage(Page):
    
    services = StreamField([
        ('services',blocks.StructBlock([
            ('entries',PortfolioBlock()),
            ('tags',TagsBlock(required=False)),
    ]))], null=True, blank=True)
    
    @property
    def get_tags(self):
        """
        Helpful property to pull out the tags saved inside the struct value
        Important: makes some hard assumptions about the names & structure
        Does not get the id of the tag, only the strings as a list
        """

        tags_all = [block.value.entries.get('tags', '').split(',') for block in self]

        tags = list(chain.from_iterable(tags_all))

        return tags
    
    content_panels = Page.content_panels + [
        StreamFieldPanel('services'),

    ]

Then in the template im just doing:

         <div class="row-4">
            
            {% for tag in page.services.get_tags %}
               {{tag}}
            {% endfor %}

          </div>

However, I can't get any result. I have really tried everything, but I can't figure how to call the property to give me the list of values.

Thank you very much in advance for your time,

Francisco


Solution

  • In your template, the line

    {% for tag in page.services.get_tags %}
    

    would be trying to access a property named get_tags on the 'services' field of the page. However, get_tags isn't defined there - it's defined as a property of the page object - so this line should be

    {% for tag in page.get_tags %}
    

    Secondly, in the line

    tags_all = [block.value.entries.get('tags', '').split(',') for block in self]
    

    you're intending to loop over all the items in the StreamField, but the self in for block in self refers to the page object. This should be for block in self.services.

    Finally, in the same line, block.value will give you the value of each block, which in this case will be a dictionary of two items, entries and tags. If you wanted to access entries (the PortfolioBlock), you would write block.value['entries'] or block.value.get('entries') rather than block.value.entries - but really you don't want that, you want to access the tags item instead - so block.value.entries.get('tags', '').split(',') should be block.value.get('tags', '').split(',').