Django Ajax、批量操作与分页实践
Django Ajax、批量操作与分页实践本章介绍不刷新整页的异步请求、文件上传、批量写入、JSON 序列化和分页。它们共同服务于更流畅的交互体验但仍必须遵循 HTTP 方法、CSRF、防护、数据校验和数据库性能等基本规则。一、Ajax 的作用与请求边界AjaxAsynchronous JavaScript and XML是浏览器通过 JavaScript 主动发起 HTTP 请求、拿到结果后仅更新局部页面的技术集合。现代请求通常传输 JSON 或表单数据而不是 XML。Ajax 不等于“没有页面跳转”而是由前端决定如何处理服务器响应。方式触发方式常见结果地址栏、a浏览器导航整页加载新的页面form原生提交GET 或 POST浏览器按响应导航或刷新Ajax / FetchJavaScript 调用前端根据响应局部更新页面Ajax 仍然是普通 HTTP 请求GET 用于读取POST/PUT/PATCH/DELETE 用于改变数据。后端必须像处理普通表单一样完成认证、权限和输入校验。二、返回 JSON使用 JsonResponse浏览器与 Django 之间交换结构化数据时JSON 是最常用格式。Python 字典不是 JSON 字符串推荐使用JsonResponse自动序列化并设置application/json响应头。# user/views.pyfromdjango.httpimportJsonResponsefromdjango.viewsimportViewclassRegisterView(View):defget(self,request,*args,**kwargs):returnrender(request,user/register.html)defpost(self,request,*args,**kwargs):usernamerequest.POST.get(username,).strip()passwordrequest.POST.get(password,)ifnotusernameornotpassword:returnJsonResponse({ok:False,error:用户名和密码不能为空,},status400)# 此处应使用 Django 认证系统处理密码不能明文保存。returnJsonResponse({ok:True,message:注册成功},status201)代码说明JSON 响应建议使用统一字段例如ok、data、error并配合合适 HTTP 状态码。不要用HttpResponse(dict)直接返回字典若手动使用json.dumps()还需自行正确设置content_type。三、jQuery Ajax 提交普通表单数据jQuery 的$.ajax()传入普通对象时默认以application/x-www-form-urlencoded形式编码因此 Django 可从request.POST读取数据。它并不会自动发送 JSON。POST 请求必须携带 Django 的 CSRF Token。模板中先输出{% csrf_token %}再从隐藏输入框读取令牌并放入请求头是较清晰的做法。!-- user/templates/user/register.html --{% load static %}scriptsrc{% static js/jquery.min.js %}/scriptformidregister-form{% csrf_token %}label用户名inputidusernamenameusernamerequired/labellabel密码inputidpasswordnamepasswordtypepasswordrequired/labelbuttonidsubmit-buttontypesubmit注册/button/formpidmessagerolestatus/p$(#register-form).on(submit,function(event){event.preventDefault();constcsrfToken$([namecsrfmiddlewaretoken]).val();$.ajax({url:window.location.pathname,type:POST,data:{username:$(#username).val(),password:$(#password).val(),},headers:{X-CSRFToken:csrfToken},dataType:json,}).done(function(data){$(#message).text(data.message);}).fail(function(xhr){constmessagexhr.responseJSON?.error||请求失败请稍后重试;$(#message).text(message);});});代码说明dataType: json表示期望服务端响应是 JSON并不会改变请求体编码。表单提交事件中调用event.preventDefault()可以阻止浏览器原生整页提交。success回调只处理成功状态使用.fail()或error回调才能处理 4xx/5xx 响应。发送 JSON 请求体当 API 明确约定使用 JSON 时应把对象序列化为字符串设置contentType: application/json并在 Django 中从request.body读取和解析。$.ajax({url:/api/calculate/,type:POST,contentType:application/json,dataType:json,headers:{X-CSRFToken:$([namecsrfmiddlewaretoken]).val()},data:JSON.stringify({number_one:12,number_two:3,operator:}),});importjsonfromdjango.httpimportJsonResponsedefcalculate(request):try:payloadjson.loads(request.body)leftfloat(payload[number_one])rightfloat(payload[number_two])except(KeyError,TypeError,ValueError,json.JSONDecodeError):returnJsonResponse({ok:False,error:参数格式错误},status400)operatorpayload.get(operator)operations{:lambda:leftright,-:lambda:left-right,*:lambda:left*right,/:lambda:left/rightifright!0elseNone,}ifoperatornotinoperations:returnJsonResponse({ok:False,error:不支持的运算符},status400)resultoperations[operator]()ifresultisNone:returnJsonResponse({ok:False,error:除数不能为 0},status400)returnJsonResponse({ok:True,result:result})代码说明解析 JSON 时应捕获格式错误并验证数据类型。涉及金额时不要使用float应使用Decimal此处仅用于简单计算示例。四、Ajax 上传文件FormData文件不能作为普通对象字段可靠地发送。浏览器需要用FormData生成multipart/form-data请求体Django 则从request.FILES读取上传文件文本字段仍在request.POST。formidavatar-form{% csrf_token %}label用户名inputidusernamenameusername/labellabel头像inputidavatarnameavatartypefileacceptimage/*/labelbuttontypesubmit上传/button/formpidupload-messagerolestatus/p$(#avatar-form).on(submit,function(event){event.preventDefault();constformDatanewFormData(this);$.ajax({url:window.location.pathname,type:POST,data:formData,processData:false,contentType:false,headers:{X-CSRFToken:$([namecsrfmiddlewaretoken]).val()},dataType:json,}).done((data)$(#upload-message).text(data.message)).fail((xhr)$(#upload-message).text(xhr.responseJSON?.error||上传失败));});fromdjango.httpimportJsonResponsedefupload_avatar(request):ifrequest.method!POST:returnJsonResponse({error:仅支持 POST},status405)avatarrequest.FILES.get(avatar)ifavatarisNone:returnJsonResponse({ok:False,error:请选择文件},status400)ifavatar.size5*1024*1024:returnJsonResponse({ok:False,error:文件不能超过 5 MB},status400)# 还应校验真实内容、扩展名和权限并使用受控存储后端保存。returnJsonResponse({ok:True,message:文件已接收})代码说明processData: false防止 jQuery 将FormData转成查询字符串contentType: false让浏览器自动生成带边界的 multipart 请求头。不要试图读取文件输入框的.val()作为真实路径浏览器会刻意隐藏本地路径。request.is_ajax()已在 Django 3.1 弃用并在后续版本移除不应使用它判断请求类型。若业务确实需要特定标记可以检查自定义请求头但接口应以响应格式和 HTTP 约定为准而不是把“是否 Ajax”作为安全边界。五、确认弹窗与安全删除确认弹窗只能改善用户体验不能代替后端权限校验。删除操作必须使用 POST 或 DELETE不能使用 GET因为 GET 应保持安全且幂等不应改变服务器数据。tableidbook-tabletrdata-book-id1td西游记/tdtdbuttonclassdelete-booktypebutton删除/button/td/tr/table$(#book-table).on(click,.delete-book,function(){constrow$(this).closest(tr);constbookIdrow.data(book-id);if(!window.confirm(确定删除这本书吗)){return;}$.ajax({url:/books/${bookId}/delete/,type:POST,headers:{X-CSRFToken:$([namecsrfmiddlewaretoken]).val()},dataType:json,}).done(function(data){if(data.ok)row.remove();}).fail(function(xhr){alert(xhr.responseJSON?.error||删除失败);});});fromdjango.contrib.auth.decoratorsimportlogin_requiredfromdjango.httpimportJsonResponsefromdjango.views.decorators.httpimportrequire_POSTfrom.modelsimportBooklogin_requiredrequire_POSTdefdelete_book(request,book_id):bookBook.objects.filter(pkbook_id).first()ifbookisNone:returnJsonResponse({ok:False,error:图书不存在},status404)# 此处还应校验 request.user 是否有删除该图书的权限。book.delete()returnJsonResponse({ok:True})代码说明页面中重复项应使用 class 而不是重复的 id。事件委托绑定到表格父元素即使后续动态添加按钮也能响应点击。SweetAlert、layer 等组件可以替代window.confirm()但后端的登录、权限、CSRF 和请求方法限制始终不可省略。六、批量插入bulk_create()逐条调用create()会执行大量 INSERT 语句导入大量数据时bulk_create()可以显著减少数据库往返次数。它应使用分批写入避免一次性创建过多 Python 对象或超出数据库参数限制。fromdecimalimportDecimalfromdjango.dbimporttransactionfrom.modelsimportBookdefimport_books(rows):batch_size1000batch[]withtransaction.atomic():forindex,rowinenumerate(rows,start1):batch.append(Book(namerow[name],priceDecimal(str(row[price])),))iflen(batch)batch_size:Book.objects.bulk_create(batch,batch_sizebatch_size)batch.clear()ifbatch:Book.objects.bulk_create(batch,batch_sizebatch_size)代码说明bulk_create()通常不会调用每个对象的save()也不会发送pre_save、post_save信号依赖这些钩子的业务逻辑需要额外处理。示例使用Decimal(str(...))避免浮点数精度问题。百万级数据导入还应考虑后台任务、进度反馈、失败重试和数据库锁影响不能直接阻塞普通 Web 请求。七、把 QuerySet 序列化为 JSON模型实例和QuerySet不能直接交给JsonResponse。接口应明确选择要公开的字段转换为基础数据类型后再返回这样既能控制响应结构也能避免泄露敏感字段。fromdjango.httpimportJsonResponsefrom.modelsimportBookdefbook_list_api(request):bookslist(Book.objects.values(id,name,price)[:100])returnJsonResponse({results:books})代码说明values()返回字典形式的QuerySetlist()触发查询并得到可 JSON 序列化的列表。返回对象包一层results可在以后添加分页、统计信息或错误字段而不破坏接口结构。django.core.serializers.serialize(json, queryset)也可将模型序列化为 JSON但输出结构包含模型标签、主键和fields嵌套通常不适合作为面向前端的稳定 API。复杂 API 更适合使用 Django REST Framework 的 Serializer 明确控制字段和验证规则。八、分页使用 Django Paginator分页避免一次性向数据库和页面加载所有记录。最基础的切片公式是第page页、每页per_page条数据对应[ (page - 1) * per_page : page * per_page ]。但业务项目应优先使用 Django 的Paginator它处理页码、总页数、边界与异常更可靠。fromdjango.core.paginatorimportEmptyPage,PageNotAnInteger,Paginatorfromdjango.shortcutsimportrenderfrom.modelsimportBookdefbook_list(request):booksBook.objects.order_by(id)paginatorPaginator(books,20)page_numberrequest.GET.get(page,1)try:page_objpaginator.page(page_number)exceptPageNotAnInteger:page_objpaginator.page(1)exceptEmptyPage:page_objpaginator.page(paginator.num_pages)returnrender(request,book/list.html,{page_obj:page_obj})!-- book/templates/book/list.html --ul{% for book in page_obj.object_list %}li{{ book.name }} - {{ book.price }}/li{% empty %}li暂无图书/li{% endfor %}/ulnavaria-label图书分页ulclasspagination{% if page_obj.has_previous %}liahref?page1首页/a/liliahref?page{{ page_obj.previous_page_number }}上一页/a/li{% endif %} {% for page in page_obj.paginator.get_elided_page_range %} {% if page page_obj.paginator.ELLIPSIS %}liclassdisabledspan{{ page }}/span/li{% elif page page_obj.number %}liclassactivespan{{ page }}/span/li{% else %}liahref?page{{ page }}{{ page }}/a/li{% endif %} {% endfor %} {% if page_obj.has_next %}liahref?page{{ page_obj.next_page_number }}下一页/a/liliahref?page{{ page_obj.paginator.num_pages }}尾页/a/li{% endif %}/ul/nav代码说明Paginator会对QuerySet做切片从而生成带LIMIT和OFFSET的查询。get_elided_page_range可在页数很多时显示省略号避免模板手写大量嵌套判断。深页码的 OFFSET 查询在超大表上可能变慢这时应考虑基于游标或主键的“键集分页”。九、实践要点Ajax 请求仍是 HTTP 请求后端必须校验方法、权限、CSRF 与输入数据。jQuery 普通对象默认发的是表单编码发送 JSON 时需JSON.stringify()和contentType: application/json。上传文件使用FormData文件从request.FILES读取并在服务端限制大小、类型和存储位置。所有删除、创建和更新操作使用非 GET 方法确认弹窗不能替代服务器权限控制。大批量写入分批bulk_create()理解它不会触发save()和模型信号。接口只返回必要字段分页优先使用Paginator而不是拼接带safe的 HTML 字符串。掌握这些做法后页面交互、数据导入和列表展示可以在保持响应速度的同时维持清晰的安全与维护边界。

相关新闻

网络摄像机RTSP地址与端口配置实战:从原理到排查全解析

网络摄像机RTSP地址与端口配置实战:从原理到排查全解析

1. 项目概述:从“连不上”到“看得见”的实战之路最近在折腾家里的安防监控,想把几个不同品牌的网络摄像机画面集成到NAS或者智能家居平台上,结果第一步就卡住了——找不到摄像机的RTSP地址和端口。这感觉就像你拿到了一把新房的钥匙&#xf…

2026/10/16 9:43:25 阅读更多 →
NDIS驱动层网络过滤实战:构建终端违规外联的底层防线

NDIS驱动层网络过滤实战:构建终端违规外联的底层防线

1. 项目概述:从“违规外联”到“合规管控”的实战思考最近在和一些做企业安全运维的朋友聊天时,大家不约而同地提到了一个让人头疼的老大难问题——“违规外联”。这个词听起来有点专业,说白了,就是公司内网里的电脑,未…

2026/10/16 19:30:31 阅读更多 →
SkillShapley:基于边界自适应Shapley值的大模型智能体技能步骤归因方法

SkillShapley:基于边界自适应Shapley值的大模型智能体技能步骤归因方法

1. 项目概述:当大模型智能体学会“论功行赏” 最近在折腾大模型智能体(LLM Agents)的朋友,估计都遇到过同一个灵魂拷问:当你的智能体完成一个复杂任务,比如写一份市场分析报告,或者调试一段代码…

2026/10/13 11:02:52 阅读更多 →

最新新闻

Claude Code模板实战:从临时助手到团队规范执行器

Claude Code模板实战:从临时助手到团队规范执行器

大概三个月前,我把 Claude Code 从一个"偶尔拿来写点脚本的玩具"正式转成了日常主力编程搭档。这三个月里我最深的体会是:模型能力的上限,其实很少是瓶颈;真正决定它好用不好用的,是你有没有一套 claude-cod…

2026/10/17 17:13:18 阅读更多 →
Claude Code 模板配置指南:从 CLAUDE.md 到自定义命令与 hooks

Claude Code 模板配置指南:从 CLAUDE.md 到自定义命令与 hooks

claude-code-templates 这个项目名,乍看像是一个平平无奇的模板仓库,但用过一段时间后我发现,它其实是 Claude Code 从“能跑”到“好用”的关键一层。Claude Code 默认状态下就像一个对项目一无所知的实习生,你让它写代码&#x…

2026/10/17 17:13:18 阅读更多 →
分层世界模型H-WM:打通机器人任务规划与运动规划的关键架构

分层世界模型H-WM:打通机器人任务规划与运动规划的关键架构

做机器人任务规划和运动控制的人,一定都经历过这样的场景:仿真环境里一切正常,一换到真实场景,机器人要么原地发呆,要么反复重规划,要么干脆撞上前方障碍物。问题往往不是某个单独算法写得不好,…

2026/10/17 17:13:18 阅读更多 →
Hermes Agent + Obsidian 打造第二大脑(三):Docker 部署详解——从零到生产环境的完整实战指南!

Hermes Agent + Obsidian 打造第二大脑(三):Docker 部署详解——从零到生产环境的完整实战指南!

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:13:18 阅读更多 →
SPC开发包源代码实战:控制图与过程能力计算落地指南

SPC开发包源代码实战:控制图与过程能力计算落地指南

简介:这份SPC开发包源代码面向工业自动化与现场总线方向的嵌入式开发者,聚焦Profibus-DP从站通信的底层实现,适合已具备C语言基础、希望深入理解协议栈细节的中高级工程师。压缩包共4个文件,包含3个c源文件与1个h头文件&#xff0…

2026/10/17 17:12:18 阅读更多 →
人工智能导论期末冲刺:知识表示、归结原理与可信度计算全攻略

人工智能导论期末冲刺:知识表示、归结原理与可信度计算全攻略

简介:这是一份山东大学《人工智能导论》课程概念汇总PDF,适合正在备考期末、考研复试或系统梳理AI基础概念的本科生与自学读者。内容以章节为主线,从智能、知识、智能特征出发,梳理人工智能定义与发展阶段;随后系统整理…

2026/10/17 17:12:18 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →