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

2024-09-30 00:27:47 发布

您现在位置:Python中文网/ 问答频道 /正文

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

Wagtail已经附带了Django REST框架和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'),
    ]

Tags: fromimportselfgetmodelsrequestcontextpage
2条回答

首先,您没有使用rest框架。我不知道你为什么提到那件事

你想在前面过滤还是在管理层过滤? 在前面,您可以添加一个按钮adding?filter=yyyyy,您可以在get_context部分捕获该上下文。这里有一个简单的过滤器

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

接下来,在前端构建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>

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

当然,将所有_标记添加到页面上下文中,并迭代所有_标记以获得所需的html

{% for tag in all_tags %}
   <label>
      <input type="checkbox" name="tag" value="{{ tag }}">
      {{ tag }}
  </label><br>
{% endfor %}

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

快乐编码

相关问题 更多 >

    热门问题