如何在Django模板中点击侧边栏分类快速过滤文章列表?哪种方式可行?
嘿,这个需求太常见了!不管是用Python后端处理还是JavaScript前端实现,都能搞定,我给你详细拆解两种方案的具体做法:
两种可行方案:后端Python(Django)实现 + 前端JavaScript实现
一、后端Python(Django)实现方式(页面刷新式过滤)
这个方案简单直接,不需要复杂的前端逻辑,还对SEO友好,适合大多数基础场景。
步骤1:修改视图函数,支持分类筛选参数
在你获取作者文章的视图里,新增对category_id GET参数的处理,利用多对多关联过滤文章:
def author_articles(request, author_id): # 先获取该作者的所有文章 list_articles = Articles.objects.filter(author_id=author_id) # 获取前端传来的分类筛选ID category_id = request.GET.get('category_id') if category_id: # 注意:这里的categories要和你Articles模型里的多对多字段名一致 list_articles = list_articles.filter(categories__id=category_id) # 把所有分类和当前选中的分类ID传给模板,用于侧边栏渲染 categories = Category.objects.all() return render(request, 'your_template.html', { 'list_articles': list_articles, 'categories': categories, 'selected_category': category_id })
步骤2:模板侧边栏添加分类筛选链接
在模板里渲染分类列表时,给每个分类链接带上category_id参数,同时标记当前选中的分类:
<!-- 侧边栏分类区域 --> <div class="sidebar"> <h3>文章分类</h3> <ul> {% for category in categories %} <li> <a href="?category_id={{ category.id }}" {% if selected_category == category.id|stringformat:"i" %}class="active"{% endif %}> {{ category.name }} </a> </li> {% endfor %} </ul> </div>
这里的active类可以加个高亮样式,让用户一眼看到当前选中的分类。
二、前端JavaScript实现方式(无刷新异步过滤)
这个方案能实现页面不刷新就更新文章列表,用户体验更好,适合追求交互流畅度的场景。
步骤1:新增API接口+调整原视图
- 原视图保持返回作者的所有文章和分类列表,不用改太多;
- 新增一个API接口,专门处理分类筛选请求,返回筛选后的文章HTML片段:
from django.template.loader import render_to_string from django.http import JsonResponse def author_articles(request, author_id): # 原视图逻辑不变,返回完整页面 list_articles = Articles.objects.filter(author_id=author_id) categories = Category.objects.all() return render(request, 'your_template.html', { 'list_articles': list_articles, 'categories': categories, 'author_id': author_id }) def filter_articles_api(request, author_id): # 处理分类筛选的API接口 category_id = request.GET.get('category_id') list_articles = Articles.objects.filter(author_id=author_id) if category_id: list_articles = list_articles.filter(categories__id=category_id) # 渲染文章列表的HTML片段(需要单独抽一个片段模板) article_html = render_to_string('article_list_partial.html', {'list_articles': list_articles}) return JsonResponse({'html': article_html})
记得在urls.py里给这个API接口配置路由哦!
步骤2:模板改造+JavaScript绑定事件
- 先把文章列表部分抽成单独的
article_list_partial.html模板,方便复用; - 在主模板里给分类链接绑定点击事件,用AJAX请求API并更新页面内容:
<!-- 侧边栏分类 --> <div class="sidebar"> <h3>文章分类</h3> <ul> {% for category in categories %} <li> <a href="#" class="category-filter-link" data-category-id="{{ category.id }}"> {{ category.name }} </a> </li> {% endfor %} </ul> </div> <!-- 文章列表容器 --> <div id="article-list-container"> {% include 'article_list_partial.html' %} </div> <script> // 获取DOM元素 const filterLinks = document.querySelectorAll('.category-filter-link'); const articleContainer = document.getElementById('article-list-container'); const authorId = {{ author_id }}; // 从模板传入作者ID filterLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); // 阻止默认跳转 // 更新选中样式 filterLinks.forEach(l => l.classList.remove('active')); this.classList.add('active'); // 获取分类ID并发送请求 const categoryId = this.dataset.categoryId; fetch(`/api/author/${authorId}/filter/?category_id=${categoryId}`) .then(res => res.json()) .then(data => { // 替换文章列表的HTML articleContainer.innerHTML = data.html; }) .catch(err => console.error('筛选出错啦:', err)); }); }); </script>
方案选择建议
- 如果你的站点需要兼顾SEO,或者不想写太多前端代码,后端Python方案是首选,简单易维护;
- 如果追求更流畅的用户体验(无刷新),或者有更多交互需求,就选前端JavaScript方案,但记得处理加载状态、错误提示这些细节哦。
内容的提问来源于stack exchange,提问作者Jackie
相关产品推荐
相关产品推荐

