You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中通过AJAX实现文章按主题筛选功能?

Django AJAX实现按主题过滤文章

问题场景

我在Django项目中已有一个基础视图,会传递Article模型的所有实例到HTML模板,通过for循环展示;同时将Topic模型的所有主题渲染为按钮。目标是点击特定主题按钮(如“政治”)时,仅展示该主题关联的文章,希望通过AJAX实现,但缺乏相关经验遇到了实现难题。之前尝试在同一个视图中处理AJAX请求,现在希望改为单独视图搭配URL /topic/<str:topic_name>。


解决方案步骤

1. 创建单独的AJAX过滤视图

保留原有的main_view负责初始页面渲染,新增专门处理主题过滤的视图,注意要将查询到的文章数据序列化为可JSON传输的格式:

# views.py
from django.http import JsonResponse
from .models import Article, Topic

def main_view(request):
    # 用order_by替代[::-1],更符合Django ORM规范
    all_articles = Article.objects.all().order_by('-id')
    top_articles = all_articles[:10]
    topics = Topic.objects.all()
    return render(request, "mainapp/main_refactor.html", {
        "all_articles": all_articles, 
        "top_articles": top_articles, 
        "topics": topics
    })

def filter_articles_by_topic(request, topic_name):
    try:
        # 通过主题名获取对应实例,再过滤关联文章
        topic = Topic.objects.get(name=topic_name)
        articles = Article.objects.filter(topics=topic).order_by('-id')
        # 将文章转换为可序列化的字典列表
        articles_data = [
            {
                'id': article.id,
                'body': article.body,
                # 可根据需求添加其他字段,如标题、发布时间等
            }
            for article in articles
        ]
        return JsonResponse({'articles': articles_data})
    except Topic.DoesNotExist:
        # 主题不存在时返回空列表和404状态码
        return JsonResponse({'articles': []}, status=404)

2. 配置URL路由

在mainapp/urls.py中添加新的路由规则,对应过滤视图:

# urls.py
from django.urls import path
from . import views

app_name = 'mainapp'

urlpatterns = [
    path('', views.main_view, name='main'),
    # 新增主题过滤路由
    path('topic/<str:topic_name>/', views.filter_articles_by_topic, name='filter_articles'),
]

3. 调整HTML模板

确保按钮的data-url正确生成,同时给单个文章项添加容器,方便后续AJAX替换内容:

{% for topic in topics %}
    <button class="topic-button" 
            data-url="{% url 'mainapp:filter_articles' topic.name %}"
            data-topic-name="{{ topic.name }}">
        {{ topic.name }}
    </button>
{% endfor %}

<section id="article-list" class="new-articles">
    {% for article in all_articles %}
        <div class="article-item">{{ article.body }}</div>
    {% endfor %}
</section>

4. 完善AJAX逻辑

实现点击按钮后的请求发送、数据接收和页面内容更新,同时添加加载状态和异常处理:

$(document).ready(function () {
    $('.topic-button').click(function () {
        var targetUrl = $(this).data('url');
        // 显示加载状态
        $('#article-list').html('<div class="loading">加载中...</div>');
        
        $.ajax({
            url: targetUrl,
            method: 'GET',
            success: function (response) {
                var articleContainer = $('#article-list');
                articleContainer.empty();

                if (response.articles.length === 0) {
                    articleContainer.html('<div class="no-articles">该主题暂无文章</div>');
                    return;
                }

                // 循环生成文章HTML并插入容器
                response.articles.forEach(function(article) {
                    var articleHtml = '<div class="article-item">' + article.body + '</div>';
                    articleContainer.append(articleHtml);
                });
            },
            error: function() {
                $('#article-list').html('<div class="error">加载文章失败,请重试</div>');
            }
        });
    });
});

关键注意事项

  • 查询优化:如果Article和Topic是多对多关系,建议使用prefetch_related('topics')减少数据库查询次数
  • JSON序列化:不能直接将Django的QuerySet传入JsonResponse,必须转换为字典或列表格式
  • 异常处理:视图中处理主题不存在的情况,避免服务器抛出未捕获异常
  • 特殊字符兼容:Django的URL路由会自动处理主题名中的特殊字符,无需额外转义

内容的提问来源于stack exchange,提问作者Ravdar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:38:18