Django 框架高级路由中尽可能以名词为主不要出现太多动词useradd 模块 功能adduser 功能 模块get/post/put/deleteuser get 用户列表user post---- 请求体参数 用户添加user post 用户列表user/1 delete 用户删除user put--- 请求体 用户修改上述请求方式是网站访问过程中的一种设计风格RESTFULL 风格Django RESTFULL Django Rest Framework DRFDjango Rest Framework简称DRF它就是 Django 的「接口专用增强包」专门用来在 Django 里快速、规范、轻松地写出 RESTful API 接口给前端、小程序、APP 提供数据。1. 它到底是干嘛的你用原生 Django 只能做网页渲染返回 HTML表单提交但你要做前后端分离项目前端 Vue/React/ 小程序后端只返回 JSON原生 Django 很麻烦。DRF 就是解决这个问题的让你用极少代码直接生成一套标准 RESTful 增删改查接口。2. 用 DRF 能得到什么最实用的 4 个功能① 自动生成 RESTful 接口你最关心的写几行代码直接拥有GET 获取列表POST 新增PUT 修改DELETE 删除URL 全是名词不带动词完全符合 RESTful。② 自动序列化模型 ↔ JSON 自动转换不用你手动拼 JSONDRF 帮你把数据库数据 → JSON 给前端把前端传的 JSON → 存进数据库③ 自带接口调试页面超级好用运行项目后直接在浏览器访问接口就能看数据发 POST/PUT/DELETE 请求测试不用装 Postman④ 内置权限、分页、过滤、认证开箱即用登录才能访问接口分页搜索过滤接口限流3. 用一句话总结它的地位Django 做网站 Django Rest Framework 用 Django 做 API 接口接口 后端给前端提供的数据通道API应用程序编程接口 长什么样为一个地址不是页面不是图片就是一串数据JSON示例{ code: 200, msg: 成功, data: { username: 小明, email: testqq.com } }4. 最简单对比一看就懂不用 DRF原生 Django 写接口代码多要自己处理 JSON要自己处理增删改查不规范用 DRF代码极少自动 JSON自动增删改查标准 RESTful自带调试页面5. 你之前学的 RESTfulDRF 就是落地工具你前面记的规则URL 用名词动作由 GET/POST/PUT/DELETE 决定user/ 获取列表user/1 删除用户这些规则DRF 全部自动帮你实现总结Django Rest Framework Django 的 API 开发神器专门帮你快速写出规范、好用、符合 RESTful 风格的后端接口。数据序列化第一步 手动拼接from django.views import View from django.http import JsonResponse from .models import Book, Press # 确保你的模型在 models.py 里定义好了 class BookView(View): def get(self, request): # 1. 从 Book 表查询数据指定字段 bookresult list( Book.objects.values( id, bookname, bookprice, bookauthor, pressdate, category, press ) ) result [] # 2. 遍历每一本书把外键 press 对应的出版社信息替换成字典 for book in bookresult: book[press] { id: book[press], pressname: Press.objects.get(idbook[press]).pressname, pressaddress: Press.objects.get(idbook[press]).pressaddress } result.append(book) # 3. 返回 JSON 数据给前端 return JsonResponse(result, safeFalse)第二步 DRF自动拼接 serializersfrom django.core import serializers def get(self,request): book .... data serializers.serializer(json,book) return ... #这种方法还实现单一对象 如果有一对多和多对多 无法进行序列化方式三DRF序列化第一步安装DRFpip install djangorestframework第二步创建DRF的序列化器class PressSerializer(serializers.Serializer): id serializers.IntegerField() pressname serializers.CharField(max_length30) pressaddress serializers.CharField(max_length50) class BookSerializer(serializers.Serializer): id serializers.IntegerField() bookname serializers.CharField(max_length50) bookprice serializers.FloatField bookauthor serializers.CharField(max_length50) pressdate serializers.DateField() # 语言 category serializers.IntegerField(choices((1, 汉语), (2, 英语), (3, 法语), (4, 日语))) # 多对一 press PressSerializer()第三步创建DRF的视图层Viewfrom rest_framework.response import Response from rest_framework.views import APIView from app01.models import * from app01.MySerializers import * class BookView(APIView): def get(self,reqeust): bookresult Book.objects.all() # 将查询到的结果进行DRF序列化 bookSerializer BookSerializer(bookresult,manyTrue) # 返回 return Response(bookSerializer.data)第四步在settings.py文件中对drf做配置INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, app01.apps.App01Config, rest_framework ]第五步启动服务访问路由数据反序列化实现数据添加操作第一步考虑添加过程中的数据提交格式{ bookname: 鹿鼎记, bookauthor: 金庸, bookprice:50, pressdate: 2026-04-28, category2: 2, press2: 1, booktype2: [1,3] }第二步在序列化器中追加特殊的反序列化字段(标记好只读和只写)和ID字段class BookSerializer(serializers.Serializer): id serializers.IntegerField(requiredFalse, read_onlyTrue) bookname serializers.CharField(max_length50) bookprice serializers.DecimalField(max_digits5, decimal_places2) bookauthor serializers.CharField(max_length50) pressdate serializers.DateField() # 只读返回给前端看的 category serializers.CharField(sourceget_category_display, read_onlyTrue) press PressSerializers(read_onlyTrue) booktype BookTypeSerializers(manyTrue, read_onlyTrue) # 只写前端传参用 category2 serializers.CharField(write_onlyTrue) press2 serializers.IntegerField(write_onlyTrue) booktype2 serializers.ListField( write_onlyTrue )第三步在视图逻辑层接收提交数据与封装序列化器对象并进行验证def post(self,request): # 接收参数 book_obj request.data # 调用orm 封装序列化器 book_ser BookSerializer(databook_obj) # 需要对封装完成以后得序列化对象做验证 # 如果得到Ture,则验证通过如果是False则需要检查序列化字段与反序列化字段 print(book_ser.is_valid())第四步调用save方法执行添加操作def post(self,request): # 接收参数 book_obj request.data # 调用orm 序列化器 book_ser BookSerializer(databook_obj) # 需要对封装完成以后得序列化对象做验证 if book_ser.is_valid(): book_ser.save() return Response(添加成功) # 返回序列化数据 return Response(添加失败)第五步在序列化器中重写create方法调用底层ORM如果没有重写create则运行报错def create(self, validated_data): # 2. 创建书籍对象 book Book.objects.create( booknamevalidated_data.get(bookname), bookpricevalidated_data.get(bookprice), bookauthorvalidated_data.get(bookauthor), pressdatevalidated_data.get(pressdate), categoryvalidated_data[category2], press_idvalidated_data[press2], ) # 3. 处理多对多书籍类型 book.booktype.add(*validated_data[booktype2]) return book第六步测试添加效果实现数据修改操作第一步 配置URLurlpatterns [ path(book/,app.views.BookView.as_view()), path(book/int:id/, app.views.BookView2.as_view()), ]第二部 在视图逻辑层接收提交数据与封装序列化器对象并进行验证class BookView2(APIView): def get(self,request,id): book Book.objects.get(idid) book BookSerializer(book) return Response(book.data) def delete(self,request,id): Book.objects.get(idid).delete() return Response({msg:删除成功}) def put(self,request,id): book Book.objects.get(idid) ser BookSerializer(book,datarequest.data,partialTrue) # 局部修改 if ser.is_valid(): ser.save() return Response({msg:修改成功}) return Response(ser.errors)第三部 增加的代码实现修改操作 重写 updatadef update(self, instance, validated_data): instance.bookname validated_data.get(bookname, instance.bookname) instance.bookprice validated_data.get(bookprice, instance.bookprice) instance.bookauthor validated_data.get(bookauthor, instance.bookauthor) instance.pressdate validated_data.get(pressdate, instance.pressdate) instance.category validated_data.get(category2, instance.get_category_display()) instance.press_id validated_data.get(press2, instance.press_id) if validated_data.get(booktype2): instance.booktype.set(validated_data[booktype2]) instance.save() return instance第 四步 测试效果补充DRF 核心参数 / 方法通俗讲解结合 ** 序列化器 (Serializer)** 日常使用场景逐个讲清附用法示例。一、instance作用接收数据库已有模型对象用于更新 / 修改数据。不传 / 传None代表新增数据传模型实例对象代表更新已有数据二、datavalidated_data1.data原始传入的前端请求数据字典未校验可能含非法字段、格式错误。来源request.data、手动传入的字典2.validated_data校验通过后的干净数据字典。必须先执行is_valid()校验成功后才能使用自动过滤非法字段、完成类型转换、执行字段校验规则写create()/update()方法时*必用ser UserSerializer(data{age: 20}) ser.is_valid() # 先校验 print(ser.data) # 原始数据 print(ser.validated_data) # 校验后合规数据age 已转为数字三、is_valid()方法作用执行全字段校验类型、长度、正则、自定义校验器等。返回值True 校验通过False 校验失败校验失败可通过ser.errors查看错误信息必写规则使用validated_data前必须先调用is_valid()。ser UserSerializer(data{age: 200}) if ser.is_valid(): ser.save() else: print(ser.errors) # 输出错误提示补充参数raise_exceptionTrue校验失败直接抛出异常DRF 会自动返回 400 响应接口常用ser.is_valid(raise_exceptionTrue)四、partial参数作用局部更新开关布尔值搭配instance更新使用。partialFalse默认全量更新所有必填字段必须传缺字段直接校验失败partialTrue局部更新只传需要修改的字段其他字段可不传场景只改用户名不改其他必填字段user User.objects.get(id1) # partialTrue 局部更新 ser UserSerializer(instanceuser, data{name:新名字}, partialTrue) ser.is_valid() ser.save()总结新增不用partial部分字段更新必须加 partialTrue。五、add()与set()针对多对多字段DRF/ORM 中专门操作ManyToManyField多对多关系的方法作用是关联 / 解绑关联数据。前置说明假设有模型文章 (Article) 和 标签 (Tag)多对多关联。1.set(可迭代对象)覆盖式设置清空原有所有关联再重新绑定新数据。传[]直接清空所有关联article Article.objects.get(id1) # 把文章标签 全部替换 为 tag1、tag2 article.tags.set([tag1, tag2])2.add(对象/主键)追加式添加不删除原有关联只新增关联关系。可传模型对象、主键 id、多个参# 在原有标签基础上额外再加一个 tag3 article.tags.add(tag3) # 也可以传id article.tags.add(3)补充对应解绑remove()# 移除指定关联保留其他 article.tags.remove(tag3)快速汇总记忆版instance传模型对象 更新不传 新增is_valid()执行数据校验失败看errorsvalidated_data校验通过的安全数据校验后才能用partialTrue 局部更新只改部分字段set()多对多 → 覆盖原有关系add()多对多 → 追加新关系保留原有DRF 2.0 版本class BookSerializer(serializers.ModelSerializer): class Meta: model Book fields __all__ extra_kwargs { press: {write_only: True}, booktype: {write_only: True}, category: {write_only: True}, } # depth 1 # 深度查询. category_display serializers.SerializerMethodField(read_onlyTrue) press_display serializers.SerializerMethodField(read_onlyTrue) booktype_display serializers.SerializerMethodField(read_onlyTrue) def get_category_display(self, obj): return obj.get_category_display() def get_press_display(self, obj): return {id:obj.press.id,pressname:obj.press.pressname} def get_booktype_display(self, obj): return [{id:i.id,typename:i.typename} for i in obj.booktype.all()]什么是序列化什么是反序列化一、核心定义1. 序列化Serialize把内存中运行的对象 / 数据结构转换成可存储、可网络传输的字节串 / 字符串格式。 内存中的对象不能直接存硬盘、发网络序列化就是做「打包」。2. 反序列化Deserialize把字节串 / 字符串还原回程序内存里原生对象 / 数据结构。相当于「解包」恢复成程序能直接调用的变量、对象。DRF中的1.0 以及 2.0 的区别特性APIViewModelViewSet定位DRF 视图体系的基础父类所有视图的 “根”基于ViewSetModelMixin的封装类专门给模型 CRUD 用CRUD 方法完全手动写get()/post()/put()/delete()自动提供list()/retrieve()/create()/update()/destroy()路由配置需手动为每个方法绑定 URL配合DefaultRouter自动生成 5 个标准接口路由自定义程度极高所有逻辑自己写中等可通过重写方法、权限类、过滤类扩展适用场景非模型接口、复杂业务逻辑、非标准请求模型的标准 CRUD 接口、快速开发后台接口DRF2.0 高级在DRF的基础上 进行封装# # 封装通用模块 # #通用模块 # class GenericAPIView(APIView): 公共父类 # queryset None # serializer_class None # # def get_queryset(self): # return self.queryset.all() # # def get_serializer_class(self,*args,**kwargs): # return self.serializer_class(*args,**kwargs) # # #通用查询所有模块 # class ListModelMixin(object): # def list(self,request): # queryset self.get_queryset() # ser_obj self.get_serializer_class(queryset,manyTrue) # return Response(ser_obj.data) # # #通用添加模块 # class CreateModelMixin(object): # def create(self,request): # ser_obj self.get_serializer_class(datarequest.data) # if ser_obj.is_valid(): # ser_obj.save() # return Response(ser_obj.validated_data) # return Response(ser_obj.errors) # # #通用查询某一个模块 # class RetrieveModelMixin(object): # def retrieve(self,request,id): # queryset self.get_queryset().get(idid) # # 序列化 # ser_obj self.get_serializer_class(queryset) # # return Response(ser_obj.data) # # #通用删除某一个模块 # class DestroyModelMixin(object): # def destroy(self,request,id): # queryset self.get_queryset().get(idid) # if not queryset: # return Response(对象不存在) # # 序列化 # queryset.delete() # return Response(删除成功) # # #通用修改某一个模块 # class UpdateModelMixin(object): # def update(self,request,id): # queryset self.get_queryset().get(idid) # ser_obj self.get_serializer_class(instancequeryset, datarequest.data, partialTrue) # if ser_obj.is_valid(): # # 调用orm执行修改 # ser_obj.save() # return Response(ser_obj.validated_data) # return Response(ser_obj.errors) # # class ListCreateApiView(GenericAPIView,ListModelMixin,CreateModelMixin): # pass # # class RetrieveDestroyUpdateApiView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin): # pass # # class BookView(ListCreateApiView): # #提前准备查询数据与序列化器 # queryset Book.objects.all() # serializer_class BookSerializer # # def get(self, request): # return self.list(request) # # def post(self, request): # return self.create(request) # # class BookEditView(RetrieveDestroyUpdateApiView): # queryset Book.objects.all() # serializer_class BookSerializer # def get(self, request, id): # return self.retrieve(request,id) # # def put(self, request, id): # return self.update(request,id) # # def delete(self, request, id): # return self.destory(request,id) # # class PressView(ListCreateApiView): # queryset Press.objects.all() # serializer_class PressSerializer # # def get(self,request): # return self.list(request) # # def post(self,request): # return self.create(request) # # class BookTypeView(ListCreateApiView): # queryset BookType.objects.all() # serializer_class BookTypeSerializer # def get(self,request): # return self.list(request) # # class PressView(APIView): # def get(self,request): # presslist Press.objects.all() # serializer PressSerializer(presslist, manyTrue) # return Response(serializer.data) # class BookView(APIView): # # def get(self,reqeust): # bookresult Book.objects.all() # # 将查询到的结果进行DRF序列化 # bookSerializer BookSerializer(bookresult,manyTrue) # # 返回 # return Response(bookSerializer.data) # # # { # bookname: 鹿鼎记, # bookauthor: 金庸, # bookprice:50, # pressdate: 2026-04-28, # category2: 2, # press2: 1, # booktype2: [1,3] # } # # def post(self,request): # # 接收参数 # book_obj request.data # # 调用orm 序列化器 # book_ser BookSerializer(databook_obj) # # 需要对封装完成以后得序列化对象做验证 # if book_ser.is_valid(): # book_ser.save() # return Response(添加成功) # # 返回序列化数据 # return Response(添加失败) # class BookEditView(APIView): # def get(self,request,id): # book Book.objects.get(idid) # # 将查询到的结果进行DRF序列化 # bookSerializer BookSerializer(book) # # 返回 # return Response(bookSerializer.data) # # def delete(self,request,id): # book Book.objects.get(idid) # book.delete() # # 返回 # return Response(删除成功) # # def put(self, request, id): # # 得到要修改的数据库中的详细对象信息 # book Book.objects.get(idid) # # # instance:原始数据 data:要修改的数据 partial:局部修改 # book_ser BookSerializer(instancebook,datarequest.data,partialTrue) # print(book_ser.is_valid()) # if book_ser.is_valid(): # book_ser.save() # return Response(修改成功)用这种方式可以减少好多类的创建以及 减少代码冗余一、整体思路总结你手写的这套代码完全复刻了 DRF 底层设计思想GenericAPIView DRF 原生GenericAPIView通用基础视图ListModelMixin/CreateModelMixin... DRF 五大混入类 (Mixin)最后组合 拼装出具备增删改查能力的视图本质抽公共代码 → 封装基类 功能混入 → 子类直接复用避免重复写get/post/序列化/查询逻辑。DRF 3.0 版本重写 URL 方法可以直接填充为 五中url 不用自己定义from rest_framework.routers import DefaultRouter from app.views import BookView router DefaultRouter() # 格式register(路由前缀, 视图类, basename唯一标识) router.register(book, BookView, basenamebook1) # router.register(book2, BookView2, basenamebook2) urlpatterns [] urlpatterns router.urls from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet): queryset Book.objects.all() serializer_class BookSerializer在 views 里面的实现 为直接继承类 不用自己在定义方法DRF3.0版本-Viewview层是继承APIView还是继承ModelViewSet结论先行 简单单接口、定制化逻辑、非标准 CRUD → 用 APIView基础视图类自由度最高 标准列表 / 详情 / 增删改查全套 CRUD、配合路由自动生成 → 用 ModelViewSet视图集开发效率最高 一、两者核心区别 1. APIView基础视图 DRF 最底层视图基于 Django 原生 View 扩展一个类对应一个接口地址。 按请求方法拆分get() / post() / put() / delete() 等 手动写路由、手动控制逻辑灵活度拉满 适合单一场景接口、复杂业务逻辑、非标准 CRUD、自定义权限 / 限流 / 响应 2. ModelViewSet视图集 封装好的全套 CRUD 视图集继承自 ViewSet一个类对应一组接口。 默认自动实现 5 个标准动作 list(查列表)、retrieve(查单个)、create(新增)、update(全改)、destroy(删除) 配合 DRF 路由器DefaultRouter/SimpleRouter自动生成路由不用手写多条路由 代码极简只需要配置 queryset 和 serializer_class 适合标准数据表 CRUD 接口、后台管理、常规业务接口 二、如何选型场景对照 优先用 APIView 接口不是标准 CRUD如登录、验证码、文件上传、统计接口、复杂查询 每个接口逻辑差异大需要深度定制请求 / 响应 / 流程 只需要单个接口不需要整套增删改查 习惯 Django 原生视图写法追求细粒度控制 优先用 ModelViewSet 对一张数据表做完整 增删改查 后台管理、常规业务接口逻辑通用无特殊定制 想少写路由、少写重复代码快速开发 三、补充衍生类常用过渡选择 如果介于两者之间还有折中方案 GenericAPIView 混入类 比 APIView 少写重复代码比 ViewSet 更灵活适合部分 CRUD。 ReadOnlyModelViewSet 只提供查询列表 详情禁用增删改纯只读接口首选。 四、一句话总结 追求灵活、定制、单接口 → APIView 追求高效、标准 CRUD、自动路由 → ModelViewSet 日常开发中后台管理 / 标准数据表优先 ModelViewSet前端业务接口、特殊功能接口优先 APIView。分页类型核心配置请求示例核心特点适用场景页码分页PageNumberPaginationpage_size默认每页条数page_query_param页码参数名page_size_query_param动态调整每页条数/list?page2size3支持直接跳页使用直观数据量大时性能下降传统分页列表、需要跳页的场景偏移分页LimitOffsetPaginationdefault_limit默认每页条数limit_query_param条数参数名offset_query_param偏移量参数名/list?offset3limit3无页码概念实现简单offset 越大查询越慢数据量较小的简单列表游标分页CursorPaginationpage_size每页条数cursor_query_param游标参数名ordering必填排序字段/list?cursorxxx依靠游标定位只能上下翻页、不能跳页大数据量性能最优不易漏 / 重数据海量数据、无限滚动、信息流、聊天记录认证机制前后端分离开发中如何判断访问的路由是否合理是否正常登录Token认证from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import User class MyAuth(BaseAuthentication): def authenticate(self, request): print(request.headers) # 判断是否有token url ?thoken706c5ed1124b4191b6f8ec786b3499ae token request.query_params.get(token) if not token: # 没有登录 raise AuthenticationFailed(您还没有登录) # 用户携带token,但是真假不确定 userobj User.objects.filter(tokentoken).first() if not userobj: raise AuthenticationFailed(登录信息有误请重新登录) return userobj,token授权机制授权机制$.ajax({ url:http://localhost:8000/app01/user/, type:delete, data:{id:1}, headers:{Authorization:Bearer loginuser.token}, success:funxxxxx }) class MyPer(): message 您没有管理员权限 def has_permission(self,request,view): print(request.user) userobj request.user print(userobj) if userobj.type 1: return True return False限流机制应用场景from rest_framework.throttling import SimpleRateThrottle class MyThrottle(SimpleRateThrottle): scope mytime def get_cache_key(self, request, view): return self.get_ident(request) # setting.py文件中配置 REST_FRAMEWORK { DEFAULT_THROTTLE_RATES:{mytime:3/m} } class UserView(APIView): # 认证组件 authentication_classes [MyAuth] # 授权组件 permission_classes [MyPer] # 限流组件 throttle_classes [MyThrottle] def get(self,request): print(用户删除) return Response(用户删除成功)分页机制from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyPage(PageNumberPagination): page_size 3 #每页显示3条 page_query_param page #下一页 user?page2 page_size_query_param size #下一页显示多少条 user?page2size3 class MyLimit(LimitOffsetPagination): default_limit 3 class MyCursor(CursorPagination): cursor_query_param cursor page_size 3 ordering -id class BookView(ModelViewSet): queryset Book.objects.all() serializer_class BookSerializer
Django 框架 深度学习 第二课程
发布时间:2026/6/11 18:28:53
Django 框架高级路由中尽可能以名词为主不要出现太多动词useradd 模块 功能adduser 功能 模块get/post/put/deleteuser get 用户列表user post---- 请求体参数 用户添加user post 用户列表user/1 delete 用户删除user put--- 请求体 用户修改上述请求方式是网站访问过程中的一种设计风格RESTFULL 风格Django RESTFULL Django Rest Framework DRFDjango Rest Framework简称DRF它就是 Django 的「接口专用增强包」专门用来在 Django 里快速、规范、轻松地写出 RESTful API 接口给前端、小程序、APP 提供数据。1. 它到底是干嘛的你用原生 Django 只能做网页渲染返回 HTML表单提交但你要做前后端分离项目前端 Vue/React/ 小程序后端只返回 JSON原生 Django 很麻烦。DRF 就是解决这个问题的让你用极少代码直接生成一套标准 RESTful 增删改查接口。2. 用 DRF 能得到什么最实用的 4 个功能① 自动生成 RESTful 接口你最关心的写几行代码直接拥有GET 获取列表POST 新增PUT 修改DELETE 删除URL 全是名词不带动词完全符合 RESTful。② 自动序列化模型 ↔ JSON 自动转换不用你手动拼 JSONDRF 帮你把数据库数据 → JSON 给前端把前端传的 JSON → 存进数据库③ 自带接口调试页面超级好用运行项目后直接在浏览器访问接口就能看数据发 POST/PUT/DELETE 请求测试不用装 Postman④ 内置权限、分页、过滤、认证开箱即用登录才能访问接口分页搜索过滤接口限流3. 用一句话总结它的地位Django 做网站 Django Rest Framework 用 Django 做 API 接口接口 后端给前端提供的数据通道API应用程序编程接口 长什么样为一个地址不是页面不是图片就是一串数据JSON示例{ code: 200, msg: 成功, data: { username: 小明, email: testqq.com } }4. 最简单对比一看就懂不用 DRF原生 Django 写接口代码多要自己处理 JSON要自己处理增删改查不规范用 DRF代码极少自动 JSON自动增删改查标准 RESTful自带调试页面5. 你之前学的 RESTfulDRF 就是落地工具你前面记的规则URL 用名词动作由 GET/POST/PUT/DELETE 决定user/ 获取列表user/1 删除用户这些规则DRF 全部自动帮你实现总结Django Rest Framework Django 的 API 开发神器专门帮你快速写出规范、好用、符合 RESTful 风格的后端接口。数据序列化第一步 手动拼接from django.views import View from django.http import JsonResponse from .models import Book, Press # 确保你的模型在 models.py 里定义好了 class BookView(View): def get(self, request): # 1. 从 Book 表查询数据指定字段 bookresult list( Book.objects.values( id, bookname, bookprice, bookauthor, pressdate, category, press ) ) result [] # 2. 遍历每一本书把外键 press 对应的出版社信息替换成字典 for book in bookresult: book[press] { id: book[press], pressname: Press.objects.get(idbook[press]).pressname, pressaddress: Press.objects.get(idbook[press]).pressaddress } result.append(book) # 3. 返回 JSON 数据给前端 return JsonResponse(result, safeFalse)第二步 DRF自动拼接 serializersfrom django.core import serializers def get(self,request): book .... data serializers.serializer(json,book) return ... #这种方法还实现单一对象 如果有一对多和多对多 无法进行序列化方式三DRF序列化第一步安装DRFpip install djangorestframework第二步创建DRF的序列化器class PressSerializer(serializers.Serializer): id serializers.IntegerField() pressname serializers.CharField(max_length30) pressaddress serializers.CharField(max_length50) class BookSerializer(serializers.Serializer): id serializers.IntegerField() bookname serializers.CharField(max_length50) bookprice serializers.FloatField bookauthor serializers.CharField(max_length50) pressdate serializers.DateField() # 语言 category serializers.IntegerField(choices((1, 汉语), (2, 英语), (3, 法语), (4, 日语))) # 多对一 press PressSerializer()第三步创建DRF的视图层Viewfrom rest_framework.response import Response from rest_framework.views import APIView from app01.models import * from app01.MySerializers import * class BookView(APIView): def get(self,reqeust): bookresult Book.objects.all() # 将查询到的结果进行DRF序列化 bookSerializer BookSerializer(bookresult,manyTrue) # 返回 return Response(bookSerializer.data)第四步在settings.py文件中对drf做配置INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, app01.apps.App01Config, rest_framework ]第五步启动服务访问路由数据反序列化实现数据添加操作第一步考虑添加过程中的数据提交格式{ bookname: 鹿鼎记, bookauthor: 金庸, bookprice:50, pressdate: 2026-04-28, category2: 2, press2: 1, booktype2: [1,3] }第二步在序列化器中追加特殊的反序列化字段(标记好只读和只写)和ID字段class BookSerializer(serializers.Serializer): id serializers.IntegerField(requiredFalse, read_onlyTrue) bookname serializers.CharField(max_length50) bookprice serializers.DecimalField(max_digits5, decimal_places2) bookauthor serializers.CharField(max_length50) pressdate serializers.DateField() # 只读返回给前端看的 category serializers.CharField(sourceget_category_display, read_onlyTrue) press PressSerializers(read_onlyTrue) booktype BookTypeSerializers(manyTrue, read_onlyTrue) # 只写前端传参用 category2 serializers.CharField(write_onlyTrue) press2 serializers.IntegerField(write_onlyTrue) booktype2 serializers.ListField( write_onlyTrue )第三步在视图逻辑层接收提交数据与封装序列化器对象并进行验证def post(self,request): # 接收参数 book_obj request.data # 调用orm 封装序列化器 book_ser BookSerializer(databook_obj) # 需要对封装完成以后得序列化对象做验证 # 如果得到Ture,则验证通过如果是False则需要检查序列化字段与反序列化字段 print(book_ser.is_valid())第四步调用save方法执行添加操作def post(self,request): # 接收参数 book_obj request.data # 调用orm 序列化器 book_ser BookSerializer(databook_obj) # 需要对封装完成以后得序列化对象做验证 if book_ser.is_valid(): book_ser.save() return Response(添加成功) # 返回序列化数据 return Response(添加失败)第五步在序列化器中重写create方法调用底层ORM如果没有重写create则运行报错def create(self, validated_data): # 2. 创建书籍对象 book Book.objects.create( booknamevalidated_data.get(bookname), bookpricevalidated_data.get(bookprice), bookauthorvalidated_data.get(bookauthor), pressdatevalidated_data.get(pressdate), categoryvalidated_data[category2], press_idvalidated_data[press2], ) # 3. 处理多对多书籍类型 book.booktype.add(*validated_data[booktype2]) return book第六步测试添加效果实现数据修改操作第一步 配置URLurlpatterns [ path(book/,app.views.BookView.as_view()), path(book/int:id/, app.views.BookView2.as_view()), ]第二部 在视图逻辑层接收提交数据与封装序列化器对象并进行验证class BookView2(APIView): def get(self,request,id): book Book.objects.get(idid) book BookSerializer(book) return Response(book.data) def delete(self,request,id): Book.objects.get(idid).delete() return Response({msg:删除成功}) def put(self,request,id): book Book.objects.get(idid) ser BookSerializer(book,datarequest.data,partialTrue) # 局部修改 if ser.is_valid(): ser.save() return Response({msg:修改成功}) return Response(ser.errors)第三部 增加的代码实现修改操作 重写 updatadef update(self, instance, validated_data): instance.bookname validated_data.get(bookname, instance.bookname) instance.bookprice validated_data.get(bookprice, instance.bookprice) instance.bookauthor validated_data.get(bookauthor, instance.bookauthor) instance.pressdate validated_data.get(pressdate, instance.pressdate) instance.category validated_data.get(category2, instance.get_category_display()) instance.press_id validated_data.get(press2, instance.press_id) if validated_data.get(booktype2): instance.booktype.set(validated_data[booktype2]) instance.save() return instance第 四步 测试效果补充DRF 核心参数 / 方法通俗讲解结合 ** 序列化器 (Serializer)** 日常使用场景逐个讲清附用法示例。一、instance作用接收数据库已有模型对象用于更新 / 修改数据。不传 / 传None代表新增数据传模型实例对象代表更新已有数据二、datavalidated_data1.data原始传入的前端请求数据字典未校验可能含非法字段、格式错误。来源request.data、手动传入的字典2.validated_data校验通过后的干净数据字典。必须先执行is_valid()校验成功后才能使用自动过滤非法字段、完成类型转换、执行字段校验规则写create()/update()方法时*必用ser UserSerializer(data{age: 20}) ser.is_valid() # 先校验 print(ser.data) # 原始数据 print(ser.validated_data) # 校验后合规数据age 已转为数字三、is_valid()方法作用执行全字段校验类型、长度、正则、自定义校验器等。返回值True 校验通过False 校验失败校验失败可通过ser.errors查看错误信息必写规则使用validated_data前必须先调用is_valid()。ser UserSerializer(data{age: 200}) if ser.is_valid(): ser.save() else: print(ser.errors) # 输出错误提示补充参数raise_exceptionTrue校验失败直接抛出异常DRF 会自动返回 400 响应接口常用ser.is_valid(raise_exceptionTrue)四、partial参数作用局部更新开关布尔值搭配instance更新使用。partialFalse默认全量更新所有必填字段必须传缺字段直接校验失败partialTrue局部更新只传需要修改的字段其他字段可不传场景只改用户名不改其他必填字段user User.objects.get(id1) # partialTrue 局部更新 ser UserSerializer(instanceuser, data{name:新名字}, partialTrue) ser.is_valid() ser.save()总结新增不用partial部分字段更新必须加 partialTrue。五、add()与set()针对多对多字段DRF/ORM 中专门操作ManyToManyField多对多关系的方法作用是关联 / 解绑关联数据。前置说明假设有模型文章 (Article) 和 标签 (Tag)多对多关联。1.set(可迭代对象)覆盖式设置清空原有所有关联再重新绑定新数据。传[]直接清空所有关联article Article.objects.get(id1) # 把文章标签 全部替换 为 tag1、tag2 article.tags.set([tag1, tag2])2.add(对象/主键)追加式添加不删除原有关联只新增关联关系。可传模型对象、主键 id、多个参# 在原有标签基础上额外再加一个 tag3 article.tags.add(tag3) # 也可以传id article.tags.add(3)补充对应解绑remove()# 移除指定关联保留其他 article.tags.remove(tag3)快速汇总记忆版instance传模型对象 更新不传 新增is_valid()执行数据校验失败看errorsvalidated_data校验通过的安全数据校验后才能用partialTrue 局部更新只改部分字段set()多对多 → 覆盖原有关系add()多对多 → 追加新关系保留原有DRF 2.0 版本class BookSerializer(serializers.ModelSerializer): class Meta: model Book fields __all__ extra_kwargs { press: {write_only: True}, booktype: {write_only: True}, category: {write_only: True}, } # depth 1 # 深度查询. category_display serializers.SerializerMethodField(read_onlyTrue) press_display serializers.SerializerMethodField(read_onlyTrue) booktype_display serializers.SerializerMethodField(read_onlyTrue) def get_category_display(self, obj): return obj.get_category_display() def get_press_display(self, obj): return {id:obj.press.id,pressname:obj.press.pressname} def get_booktype_display(self, obj): return [{id:i.id,typename:i.typename} for i in obj.booktype.all()]什么是序列化什么是反序列化一、核心定义1. 序列化Serialize把内存中运行的对象 / 数据结构转换成可存储、可网络传输的字节串 / 字符串格式。 内存中的对象不能直接存硬盘、发网络序列化就是做「打包」。2. 反序列化Deserialize把字节串 / 字符串还原回程序内存里原生对象 / 数据结构。相当于「解包」恢复成程序能直接调用的变量、对象。DRF中的1.0 以及 2.0 的区别特性APIViewModelViewSet定位DRF 视图体系的基础父类所有视图的 “根”基于ViewSetModelMixin的封装类专门给模型 CRUD 用CRUD 方法完全手动写get()/post()/put()/delete()自动提供list()/retrieve()/create()/update()/destroy()路由配置需手动为每个方法绑定 URL配合DefaultRouter自动生成 5 个标准接口路由自定义程度极高所有逻辑自己写中等可通过重写方法、权限类、过滤类扩展适用场景非模型接口、复杂业务逻辑、非标准请求模型的标准 CRUD 接口、快速开发后台接口DRF2.0 高级在DRF的基础上 进行封装# # 封装通用模块 # #通用模块 # class GenericAPIView(APIView): 公共父类 # queryset None # serializer_class None # # def get_queryset(self): # return self.queryset.all() # # def get_serializer_class(self,*args,**kwargs): # return self.serializer_class(*args,**kwargs) # # #通用查询所有模块 # class ListModelMixin(object): # def list(self,request): # queryset self.get_queryset() # ser_obj self.get_serializer_class(queryset,manyTrue) # return Response(ser_obj.data) # # #通用添加模块 # class CreateModelMixin(object): # def create(self,request): # ser_obj self.get_serializer_class(datarequest.data) # if ser_obj.is_valid(): # ser_obj.save() # return Response(ser_obj.validated_data) # return Response(ser_obj.errors) # # #通用查询某一个模块 # class RetrieveModelMixin(object): # def retrieve(self,request,id): # queryset self.get_queryset().get(idid) # # 序列化 # ser_obj self.get_serializer_class(queryset) # # return Response(ser_obj.data) # # #通用删除某一个模块 # class DestroyModelMixin(object): # def destroy(self,request,id): # queryset self.get_queryset().get(idid) # if not queryset: # return Response(对象不存在) # # 序列化 # queryset.delete() # return Response(删除成功) # # #通用修改某一个模块 # class UpdateModelMixin(object): # def update(self,request,id): # queryset self.get_queryset().get(idid) # ser_obj self.get_serializer_class(instancequeryset, datarequest.data, partialTrue) # if ser_obj.is_valid(): # # 调用orm执行修改 # ser_obj.save() # return Response(ser_obj.validated_data) # return Response(ser_obj.errors) # # class ListCreateApiView(GenericAPIView,ListModelMixin,CreateModelMixin): # pass # # class RetrieveDestroyUpdateApiView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin): # pass # # class BookView(ListCreateApiView): # #提前准备查询数据与序列化器 # queryset Book.objects.all() # serializer_class BookSerializer # # def get(self, request): # return self.list(request) # # def post(self, request): # return self.create(request) # # class BookEditView(RetrieveDestroyUpdateApiView): # queryset Book.objects.all() # serializer_class BookSerializer # def get(self, request, id): # return self.retrieve(request,id) # # def put(self, request, id): # return self.update(request,id) # # def delete(self, request, id): # return self.destory(request,id) # # class PressView(ListCreateApiView): # queryset Press.objects.all() # serializer_class PressSerializer # # def get(self,request): # return self.list(request) # # def post(self,request): # return self.create(request) # # class BookTypeView(ListCreateApiView): # queryset BookType.objects.all() # serializer_class BookTypeSerializer # def get(self,request): # return self.list(request) # # class PressView(APIView): # def get(self,request): # presslist Press.objects.all() # serializer PressSerializer(presslist, manyTrue) # return Response(serializer.data) # class BookView(APIView): # # def get(self,reqeust): # bookresult Book.objects.all() # # 将查询到的结果进行DRF序列化 # bookSerializer BookSerializer(bookresult,manyTrue) # # 返回 # return Response(bookSerializer.data) # # # { # bookname: 鹿鼎记, # bookauthor: 金庸, # bookprice:50, # pressdate: 2026-04-28, # category2: 2, # press2: 1, # booktype2: [1,3] # } # # def post(self,request): # # 接收参数 # book_obj request.data # # 调用orm 序列化器 # book_ser BookSerializer(databook_obj) # # 需要对封装完成以后得序列化对象做验证 # if book_ser.is_valid(): # book_ser.save() # return Response(添加成功) # # 返回序列化数据 # return Response(添加失败) # class BookEditView(APIView): # def get(self,request,id): # book Book.objects.get(idid) # # 将查询到的结果进行DRF序列化 # bookSerializer BookSerializer(book) # # 返回 # return Response(bookSerializer.data) # # def delete(self,request,id): # book Book.objects.get(idid) # book.delete() # # 返回 # return Response(删除成功) # # def put(self, request, id): # # 得到要修改的数据库中的详细对象信息 # book Book.objects.get(idid) # # # instance:原始数据 data:要修改的数据 partial:局部修改 # book_ser BookSerializer(instancebook,datarequest.data,partialTrue) # print(book_ser.is_valid()) # if book_ser.is_valid(): # book_ser.save() # return Response(修改成功)用这种方式可以减少好多类的创建以及 减少代码冗余一、整体思路总结你手写的这套代码完全复刻了 DRF 底层设计思想GenericAPIView DRF 原生GenericAPIView通用基础视图ListModelMixin/CreateModelMixin... DRF 五大混入类 (Mixin)最后组合 拼装出具备增删改查能力的视图本质抽公共代码 → 封装基类 功能混入 → 子类直接复用避免重复写get/post/序列化/查询逻辑。DRF 3.0 版本重写 URL 方法可以直接填充为 五中url 不用自己定义from rest_framework.routers import DefaultRouter from app.views import BookView router DefaultRouter() # 格式register(路由前缀, 视图类, basename唯一标识) router.register(book, BookView, basenamebook1) # router.register(book2, BookView2, basenamebook2) urlpatterns [] urlpatterns router.urls from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet): queryset Book.objects.all() serializer_class BookSerializer在 views 里面的实现 为直接继承类 不用自己在定义方法DRF3.0版本-Viewview层是继承APIView还是继承ModelViewSet结论先行 简单单接口、定制化逻辑、非标准 CRUD → 用 APIView基础视图类自由度最高 标准列表 / 详情 / 增删改查全套 CRUD、配合路由自动生成 → 用 ModelViewSet视图集开发效率最高 一、两者核心区别 1. APIView基础视图 DRF 最底层视图基于 Django 原生 View 扩展一个类对应一个接口地址。 按请求方法拆分get() / post() / put() / delete() 等 手动写路由、手动控制逻辑灵活度拉满 适合单一场景接口、复杂业务逻辑、非标准 CRUD、自定义权限 / 限流 / 响应 2. ModelViewSet视图集 封装好的全套 CRUD 视图集继承自 ViewSet一个类对应一组接口。 默认自动实现 5 个标准动作 list(查列表)、retrieve(查单个)、create(新增)、update(全改)、destroy(删除) 配合 DRF 路由器DefaultRouter/SimpleRouter自动生成路由不用手写多条路由 代码极简只需要配置 queryset 和 serializer_class 适合标准数据表 CRUD 接口、后台管理、常规业务接口 二、如何选型场景对照 优先用 APIView 接口不是标准 CRUD如登录、验证码、文件上传、统计接口、复杂查询 每个接口逻辑差异大需要深度定制请求 / 响应 / 流程 只需要单个接口不需要整套增删改查 习惯 Django 原生视图写法追求细粒度控制 优先用 ModelViewSet 对一张数据表做完整 增删改查 后台管理、常规业务接口逻辑通用无特殊定制 想少写路由、少写重复代码快速开发 三、补充衍生类常用过渡选择 如果介于两者之间还有折中方案 GenericAPIView 混入类 比 APIView 少写重复代码比 ViewSet 更灵活适合部分 CRUD。 ReadOnlyModelViewSet 只提供查询列表 详情禁用增删改纯只读接口首选。 四、一句话总结 追求灵活、定制、单接口 → APIView 追求高效、标准 CRUD、自动路由 → ModelViewSet 日常开发中后台管理 / 标准数据表优先 ModelViewSet前端业务接口、特殊功能接口优先 APIView。分页类型核心配置请求示例核心特点适用场景页码分页PageNumberPaginationpage_size默认每页条数page_query_param页码参数名page_size_query_param动态调整每页条数/list?page2size3支持直接跳页使用直观数据量大时性能下降传统分页列表、需要跳页的场景偏移分页LimitOffsetPaginationdefault_limit默认每页条数limit_query_param条数参数名offset_query_param偏移量参数名/list?offset3limit3无页码概念实现简单offset 越大查询越慢数据量较小的简单列表游标分页CursorPaginationpage_size每页条数cursor_query_param游标参数名ordering必填排序字段/list?cursorxxx依靠游标定位只能上下翻页、不能跳页大数据量性能最优不易漏 / 重数据海量数据、无限滚动、信息流、聊天记录认证机制前后端分离开发中如何判断访问的路由是否合理是否正常登录Token认证from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import User class MyAuth(BaseAuthentication): def authenticate(self, request): print(request.headers) # 判断是否有token url ?thoken706c5ed1124b4191b6f8ec786b3499ae token request.query_params.get(token) if not token: # 没有登录 raise AuthenticationFailed(您还没有登录) # 用户携带token,但是真假不确定 userobj User.objects.filter(tokentoken).first() if not userobj: raise AuthenticationFailed(登录信息有误请重新登录) return userobj,token授权机制授权机制$.ajax({ url:http://localhost:8000/app01/user/, type:delete, data:{id:1}, headers:{Authorization:Bearer loginuser.token}, success:funxxxxx }) class MyPer(): message 您没有管理员权限 def has_permission(self,request,view): print(request.user) userobj request.user print(userobj) if userobj.type 1: return True return False限流机制应用场景from rest_framework.throttling import SimpleRateThrottle class MyThrottle(SimpleRateThrottle): scope mytime def get_cache_key(self, request, view): return self.get_ident(request) # setting.py文件中配置 REST_FRAMEWORK { DEFAULT_THROTTLE_RATES:{mytime:3/m} } class UserView(APIView): # 认证组件 authentication_classes [MyAuth] # 授权组件 permission_classes [MyPer] # 限流组件 throttle_classes [MyThrottle] def get(self,request): print(用户删除) return Response(用户删除成功)分页机制from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyPage(PageNumberPagination): page_size 3 #每页显示3条 page_query_param page #下一页 user?page2 page_size_query_param size #下一页显示多少条 user?page2size3 class MyLimit(LimitOffsetPagination): default_limit 3 class MyCursor(CursorPagination): cursor_query_param cursor page_size 3 ordering -id class BookView(ModelViewSet): queryset Book.objects.all() serializer_class BookSerializer