简体   繁体   中英

passing tags to sidebar on wagtail

I wish to pass my app tags and categories to a sidebar. Using the RoutablePageMixin the user can display all tags/categories with the a given value either from the link in the detailPage or from the sidebar.

The categories pass as expected and the tags can be displayed, but only from the DetailPage. When I try to access the on the IndexPage/Sidebar I receive an error:

Reverse for 'post_by_tag' with arguments '('',)' not found. 1 pattern(s) tried: ['tag/(?P<tag>[-\\w]+)/$'] 

...I struggle to find the reason as post_by_tag works well when one retrieves the information from the detail_page.

I tried and retried from scratch and am still at square one. I'd highly appreciate any input or reference that could help my code to pass the tags to the sidebar menu.

below I note the relevant parts of my models, templatetags, templates. Hope it's not too long. I noted the categories in the models for comparaison. Noting that thereafter it's indentical, ie the categories codes/location/etc are the same place where category replaces tag.

Models.py

class PaintingDetailPage(Page):
...
    tags = ClusterTaggableManager(through="catalog.PaintingPageTag", blank=True)
    categories = ParentalManyToManyField("catalog.PaintingCategory", blank=True)
...
    @property
    def painting_index_page(self):
        return self.get_parent().specific

    def get_context(self, request, *args, **kwargs):
        context = super(PaintingDetailPage, self).get_context(request, *args, **kwargs)
        context['painting_index_page'] = self.painting_index_page
        context['post'] = self
        return context
class PaintingIndexPage(RoutablePageMixin, Page):
    subtitle = RichTextField...

    def get_context(self, request, *args, **kwargs):
        context = super(PaintingIndexPage, self).get_context(request, *args, **kwargs)
        context['posts'] = self.posts
        context['painting_index_page'] = self
        return context

    def get_posts(self):
        return PaintingDetailPage.objects.descendant_of(self).live()

    @route(r'^tag/(?P<tag>[-\w]+)/$')
    def post_by_tag(self, request, tag, *args, **kwargs):
        self.search_type = 'tag'
        self.search_term = tag
        self.posts = self.get_posts().filter(tags__slug=tag)
        return Page.serve(self, request, *args, **kwargs)
        #return self.render(request)

    @route(r'^category/(?P<category>[-\w]+)/$')
    def post_by_category(self, request, category, *args, **kwargs):
        self.search_type = 'category'
        self.search_term = category
        self.posts = self.get_posts().filter(categories__slug=category)
        return Page.serve(self, request, *args, **kwargs)


# TAGS
class PaintingPageTag(TaggedItemBase):
    content_object = ParentalKey(
        'PaintingDetailPage',
        related_name='post_tags',
        on_delete=models.CASCADE,
    )   
@register_snippet
class Tag(TaggitTag):
    class Meta:
        proxy = True

# CATEGORY
class PaintingCategory(models.Model):
    name = models.CharField(max_length=255)
    slug = AutoSlugField(populate_from="name",editable=True)

    panels =...

    class Meta:
        verbose_name = "Painting Category"
        verbose_name_plural = "Painting Categories"
        ordering = ["name"]

    def __str__(self):
        return self.name
register_snippet(PaintingCategory)

Templatetags.py

@register.inclusion_tag('catalog/components/tags_list.html',
                        takes_context=True)
def tags_list(context):
    tags = Tag.objects.all()
    return {
        'request': context['request'],
        'painting_index_page': context['painting_index_page'],
        'tags': tags
    }


@register.inclusion_tag("catalog/components/painting_tags_list.html", takes_context=True)
def painting_tags_list(context):
    page = context["page"]
    painting_tags = page.painting_tags.all()
    return {
        "request": context["request"],
        "tags": tags,
    }

tags_list.html

{% load wagtailroutablepage_tags wagtailcore_tags %}
<div class="card">
...
          {% for tag in tags %}
            <li>
      <a href="{% routablepageurl painting_index_page "post_by_tag" tag.slug %}" class="text-decoration-none">
        <span class="badge bg-secondary">{{ tag }}</span>
      </a>
...
</div>

sidebar.html

{% load catalogapp_tags wagtailroutablepage_tags %}
<div id="mySidebar" class="sidebar">
  <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
  
  {% categories_list %}
  {% tags_list %}
  
</div>...

The error to me suggests that you have a tag with an empty string as the slug - the error message is a little hard to unpick, but it's giving ('',) as the list of arguments being passed to post_by_tag - a list consisting of one argument, the empty string. This isn't valid for the URL pattern @route(r'^tag/(?P<tag>[-\\w]+)/$') (which requires it to contain at least one letter, number or hyphen).

To confirm this, I'd add a print line to tags_list to see exactly what it's trying to use as the slug:

@register.inclusion_tag('catalog/components/tags_list.html',
                        takes_context=True)
def tags_list(context):
    tags = Tag.objects.all()
    print([tag.slug for tag in tags])
    return {
        'request': context['request'],
        'painting_index_page': context['painting_index_page'],
        'tags': tags
    }

If this is indeed the problem, the quick fix is to filter out blank slugs with something like Tag.objects.exclude(slug='') , although it would probably be worth investigating how that empty slug got there in the first place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM