通过多个博客标签索引或过滤 Wagtail 博客文章

Esp*_*ind 4 python django wagtail

我使用 Wagtail 的教程创建了一个基本的 Wagtail 博客页面。但是,现在我想在博客页面上创建一个过滤器,允许我通过多个博客标签索引博客页面。

Wagtail 已经带有 Django REST Framework 和 Django-Taggit。是否有一种简单的方法可以使用预先打包的依赖项在 models.py 和 HTML 模板中创建过滤器?

如果没有,我可以使用哪些其他方法通过多个博客标签来索引 Wagtail 的博客页面?

from django.db import models

from modelcluster.fields import ParentalKey
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase

from wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index


class BlogIndexPage(Page):
    intro = RichTextField(blank=True)

    def get_context(self, request):
        context = super().get_context(request)
        blogpages = self.get_children().live().order_by('-first_published_at')
        context['blogpages'] = blogpages
        return context


class BlogPageTag(TaggedItemBase):
    content_object = ParentalKey(
        'BlogPage',
        related_name='tagged_items',
        on_delete=models.CASCADE
    )


class BlogPage(Page):
    date = models.DateField("Post date")
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)

    def main_image(self):
        gallery_item = self.gallery_images.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            FieldPanel('date'),
            FieldPanel('tags'),
        ], heading="Blog information"),
        FieldPanel('intro'),
        FieldPanel('body'),
        InlinePanel('gallery_images', label="Gallery images"),
    ]


class BlogTagIndexPage(Page):

    def get_context(self, request):

        # Filter by tag
        tag = request.GET.get('tag')
        blogpages = BlogPage.objects.filter(tags__name=tag)

        # Update template context
        context = super().get_context(request)
        context['blogpages'] = blogpages
        return context


class BlogPageGalleryImage(Orderable):
    page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
    image = models.ForeignKey('wagtailimages.Image', on_delete=models.CASCADE, related_name='+')
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        ImageChooserPanel('image'),
        FieldPanel('caption'),
    ]
Run Code Online (Sandbox Code Playgroud)

all*_*aps 5

url 查询字符串参数可能会出现多次。例如:

https://domain.tld/path/to/your/blog_tag_index_page/?tag=foo&tag=bar&tag=ni

从请求中获取多个值的方法是 request.GET.getlist('tag')

def get_context(self, request): 
    tags = request.GET.getlist('tag')
    blogpages = BlogPage.objects.filter(tags__name__in=tags)

    # Update template context
    context = super().get_context(request)
    context['blogpages'] = blogpages
    return context
Run Code Online (Sandbox Code Playgroud)

接下来,在前端构建 url。使用方法 get 和复选框创建一个 from。复选框都应该具有相同的name="tag"属性。

<!DOCTYPE html>
<html>
<body>
<form action="." method="get">  
  <label>
      <input type="checkbox" name="tag" value="foo">
      Foo
  </label><br>

  <label>
      <input type="checkbox" name="tag" value="bar">
      Bar
  </label><br>

  <label>
      <input type="checkbox" name="tag" value="ni">
      Ni
  </label><br>

  <input type="submit" value="Submit">
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

如果您不想要复选框,您可以创建一些其他界面并使 Javascript 更新 url。

当然,将 all_tags 添加到您的页面上下文并遍历 all_tags 以获得所需的 html。

{% for tag in all_tags %}
   <label>
      <input type="checkbox" name="tag" value="{{ tag }}">
      {{ tag }}
  </label><br>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

这是未经测试的代码,但理论上它应该可以 TM 工作。

快乐编码。