在上一章节中,我们完成了 Django 模型配置、页面数据渲染的核心流程,本节课将聚焦静态资源加载和Ajax 异步请求,实现投票项目中 “好评 / 差评” 的无刷新交互功能,进一步提升用户体验。
在 Web 项目中,静态资源(CSS、JS、图片、字体等)是页面样式和交互的基础,Django 提供了完善的静态资源管理机制,以下是具体配置步骤。

在vote项目根目录下,创建名为static的文件夹,按类型拆分子目录,规范资源管理:
static/├── css/ # 存放CSS样式文件├── js/ # 存放JavaScript脚本文件└── images/ # 存放图片资源(如教师头像、热门标签图标)修改项目settings.py文件,添加静态资源目录映射和访问前缀配置:
import os# 项目根目录BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 静态资源目录(开发环境)STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]# 静态资源访问前缀(页面中引用资源的URL开头)STATIC_URL = '/static/'接下来就可以实现“好评”和“差评”的功能了,很明显如果能够在不刷新页面的情况下实现这两个功能会带来更好的用户体验,因此我们考虑使用Ajax技术来实现“好评”和“差评”。
Ajax(Asynchronous JavaScript And XML)即异步 JavaScript 和 XML,核心能力是:在不刷新整个页面的前提下,实现页面局部内容更新。传统统 Web 应用 vs Ajax 应用

对于使用Ajax技术的Web应用,浏览器可以向服务器发起异步请求来获取数据。异步请求不会中断用户体验,当服务器返回了新的数据,我们可以通过JavaScript代码进行DOM操作来实现对页面的局部刷新,这样就相当于在不刷新整个页面的情况下更新了页面的内容,如下图所示。

Ajax 请求中,前端与后端常用 XML/JSON 交换数据,目前 JSON 已完全取代 XML,成为主流格式:
XML格式(冗余、解析复杂)
<?xml version="1.0" encoding="utf-8"?><message><from>Alice</from><to>Bob</to><content>Dinner is on me!</content></message>JSON格式(紧凑、解析便捷)
{"from":"Alice","to":"Bob","content":"Dinner is on me!"}核心优势:
我们将基于 jQuery 封装的 Ajax 方法,实现 “好评 / 差评” 的无刷新投票功能,核心流程:前端绑定点击事件 → 发送异步请求 → 后端处理逻辑 → 返回 JSON 数据 → 前端更新页面。
修改项目urls.py,为 “好评 / 差评” 映射专属 URL,指向同一视图函数:
from django.contrib import adminfrom django.urls import pathfrom vote import viewsurlpatterns = [ path('', views.show_subjects), path('teachers/', views.show_teachers), path('praise/', views.praise_or_criticize), path('criticize/', views.praise_or_criticize), path('admin/', admin.site.urls),]在polls/views.py中,新增praise_or_criticize函数,处理投票逻辑并返回 JSON 响应:
defpraise_or_criticize(request):"""好评"""try: tno = int(request.GET.get('tno')) teacher = Teacher.objects.get(no=tno)if request.path.startswith('/praise'): teacher.good_count += 1 count = teacher.good_countelse: teacher.bad_count += 1 count = teacher.bad_count teacher.save() data = {'code': 20000, 'mesg': '操作成功', 'count': count}except (ValueError, Teacher.DoseNotExist): data = {'code': 20001, 'mesg': '操作失败'}return JsonResponse(data)引入 jQuery 库,绑定点击事件,发送 Ajax 请求并更新页面:
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>老师信息</title><style>#container {width: 80%;margin: 10px auto; }.teacher {width: 100%;margin: 0 auto;padding: 10px0;border-bottom: 1px dashed gray;overflow: auto; }.teacher>div {float: left; }.photo {height: 140px;border-radius: 75px;overflow: hidden;margin-left: 20px; }.info {width: 75%;margin-left: 30px; }.infodiv {clear: both;margin: 5px10px; }.infospan {margin-right: 25px; }.infoa {text-decoration: none;color: darkcyan; }</style></head><body><divid="container"><h1>{{ subject.name }}学科的老师信息</h1><hr> {% if not teachers %}<h2>暂无该学科老师信息</h2> {% endif %} {% for teacher in teachers %}<divclass="teacher"><divclass="photo"><imgsrc="/static/images/{{ teacher.photo }}"height="140"alt=""></div><divclass="info"><div><span><strong>姓名:{{ teacher.name }}</strong></span><span>性别:{{ teacher.sex | yesno:'男,女' }}</span><span>出生日期:{{ teacher.birth }}</span></div><divclass="intro">{{ teacher.intro }}</div><divclass="comment"><ahref="/praise/?tno={{ teacher.no }}">好评</a> (<strong>{{ teacher.good_count }}</strong>) <ahref="/criticize/?tno={{ teacher.no }}">差评</a> (<strong>{{ teacher.bad_count }}</strong>)</div></div></div> {% endfor %}<ahref="/">返回首页</a></div><scriptsrc="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script><script> $(() => { $('.comment>a').on('click', (evt) => { evt.preventDefault()let url = $(evt.target).attr('href') $.getJSON(url, (json) => {if (json.code == 20000) { $(evt.target).next().text(json.count) } else {alert(json.mesg) } }) }) })</script></body></html>href="/praise/?tno={{ teacher.no }}"改为href="javascript:;",避免页面跳转,仅作为事件触发载体;data-tno属性存储教师编号,替代 URL 拼接,更优雅且易维护;bind(this)确保 Ajax 回调函数中可访问点击的按钮元素;上面的前端代码中,使用了jQuery库封装的getJSON方法向服务器发送异步请求,如果不熟悉前端的jQuery库,可以参考《jQuery API手册》。
本次实战完成了:
至此,投票项目的核心交互功能已完成。下一章节将讲解用户登录认证,要求用户必须登录才能投票,并实现用户注册功能,进一步完善项目权限控制。
国内直接使用顶级AI工具
谷歌浏览器访问:https://www.nezhasoft.cloud/r/vMPJZr
