如何在Django Wagtail中实现Tags与Categories独立管理及文章筛选
可行实现方案
你当前的模型基础已经完成了80%的需求,只需要补充筛选逻辑和模板适配即可实现完整的分类、标签独立管理及关联文章展示功能,具体操作如下:
1. 代码修正与补充
首先删除你代码中无用的导入语句:
# 删掉这行,没有实际调用 from django.utils.translation import deactivate_all
1.1 给博客列表页补充筛选逻辑
修改BlogsPage类,增加上下文处理方法,支持按分类、标签筛选文章:
class BlogsPage(Page): description = models.CharField(max_length=255, blank=True,) content_panels = Page.content_panels + [FieldPanel("description", classname="full")] def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) # 先获取所有已发布的公开文章 post_queryset = PostPage.objects.live().public().order_by('-first_published_at') # 按分类筛选 category_slug = request.GET.get('category', None) if category_slug: category = BlogsCategory.objects.filter(slug=category_slug).first() if category: post_queryset = post_queryset.filter(categories__blogs_category=category) context['current_category'] = category # 按标签筛选 tag_slug = request.GET.get('tag', None) if tag_slug: tag = Tag.objects.filter(slug=tag_slug).first() if tag: post_queryset = post_queryset.filter(tags=tag) context['current_tag'] = tag context['posts'] = post_queryset context['all_categories'] = BlogsCategory.objects.all() context['all_tags'] = Tag.objects.all() return context
1.2 给文章页增加便捷属性(可选,简化模板调用)
修改PostPage类,增加快速获取关联分类的属性:
class PostPage(Page): # 原有字段保持不变 header_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) tags = ClusterTaggableManager(through="blogs.PostPageTag", blank=True) # 新增便捷属性 @property def related_categories(self): return [item.blogs_category for item in self.categories.all()] content_panels = Page.content_panels + [ ImageChooserPanel("header_image"), # 这里可以把label改成复数更合理,支持选多个分类 InlinePanel("categories", label="分类"), FieldPanel("tags"), ]
2. 模板适配
2.1 博客列表页模板(blogs/blogs_page.html)
实现分类、标签筛选入口,以及筛选后的文章列表展示:
<!-- 分类筛选区 --> <div class="category-filter"> <h3>文章分类</h3> {% for cat in all_categories %} <a href="?category={{ cat.slug }}" class="{% if current_category and current_category.slug == cat.slug %}active{% endif %}"> {{ cat.name }} </a> {% endfor %} </div> <!-- 标签筛选区 --> <div class="tag-filter"> <h3>文章标签</h3> {% for tag in all_tags %} <a href="?tag={{ tag.slug }}" class="{% if current_tag and current_tag.slug == tag.slug %}active{% endif %}"> {{ tag.name }} </a> {% endfor %} </div> <!-- 文章列表 --> <div class="post-list"> {% for post in posts %} <div class="post-item"> <h4><a href="{{ post.url }}">{{ post.title }}</a></h4> <p>发布时间:{{ post.first_published_at|date:"Y-m-d" }}</p> </div> {% empty %} <p>当前分类/标签下暂无相关文章</p> {% endfor %} </div>
2.2 文章详情页模板(blogs/post_page.html)
展示当前文章关联的分类、标签,点击可跳转对应筛选列表:
<!-- 文章详情内容省略 --> <div class="post-meta"> <!-- 关联分类 --> <div class="post-categories"> 分类: {% for cat in page.related_categories %} <a href="{{ page.get_parent.url }}?category={{ cat.slug }}">{{ cat.name }}</a>{% if not forloop.last %}、{% endif %} {% endfor %} </div> <!-- 关联标签 --> <div class="post-tags"> 标签: {% for tag in page.tags.all %} <a href="{{ page.get_parent.url }}?tag={{ tag.slug }}">{{ tag.name }}</a>{% if not forloop.last %}、{% endif %} {% endfor %} </div> </div>
3. 后台使用说明
你已经将分类、标签注册为Wagtail Snippet,直接在后台左侧「Snippets」菜单中就能找到「Categories」和「Tag」两个管理入口,可以独立新增、编辑、删除分类和标签,无需和文章绑定操作。创建文章时直接从已有的分类、标签中选择即可。
内容的提问来源于stack exchange,提问作者soupi
相关产品推荐
相关产品推荐

