drf请求、响应编码格式、视图类、视图扩展类
drf请求之Request类
1、新的request视图层的方法中的request都是这个类(from rest_framework.request import Request)的对象
2、使用request.data 取请求体中的数据(之前的Json传值request.body)
3、使用request.query_params 取请求参数中的数据
4、其他属性,用起来和之前一样
-request.method 的时候---》实际上 request._request.'method'---》反射出来的
-这个类from rest_framework.request import Request没有method,他会触发这个类的__getattr__---》
5 、FILES 用起来跟之前一样,前端传入的文件在里面
了解:
视图类方法中,self是咱们写的视图类 对象,self.request是新的request
控制前端请求的编码格式
前端传入的编码:urlencoded、json、form-data
某些接口只能接收到某种编码的处理方式
方式一:
FormParser:urlencoded
MultiPartParser:form-data
局部使用—在视图类上配置,且优先使用他
class BookView(APIView): # 视图类内的所有方法,只能接收json格式
parser_classes = [JSONParser]
方式二:
全局生效,在配置文件中写,所有接口都支持某一种或者某几种
全局使用后,再局部使用,只需要在视图类上加上即可,因为优先使用视图类
# 全局如果用了,局部这样配,优先用局部的,也就是这个类管理的接口,只能接收form-data格式
class BookView(APIView):
parser_classes = [MultiPartParser]
drf自己有默认配置,默认配置就是支持三种,所以我们即使没有配置,也可以使用三种。
drf之响应
drf之Response对象源码
Response
__init__ 中需要传这几个参数,不传也可以
data=None # 字符串,列表,字典----》放在了响应 体 中 ---》第一个参数是它
status = None #http响应状态码,默认是200,可以改成3xx、4xx、5xx,不能改为1xx,因为1xx请求正在处理中,执行代码后会崩掉
content_type=None #响应编码格式(这个不用管,用浏览器访问就是text/html,用postman就是:json格式)
template_name=None #模板名字 默认是:rest_framework/api.html 可以定制自己返回页面的样式
通过res.data可以取到当时放的data
res=Response(data={},status=500,headers={'xxx':'yyy'}) #响应状态码是500,请求头是{'xxx':'yyy'}
print(res.data) #{}
return res
取当时放的响应头:
res.headers 拿不到数据,可以通过下面的方式或得到
print(res['xxx']) #yyy
print(res.has_header('zzz')) #False 这里是判断请求头是否是zzz
源码:
原生django怎么给响应头写入数据
直接在HttpResponse响应对象中添加键值对
JsonResponse也是同理,在响应对象中添加键值对
drf之响应格式
响应编码格式:默认支持json和text/html(浏览器)
局部使用:
class BookView(APIView):
renderer_classes = [BrowsableAPIRenderer] #只支持浏览器格式
全局使用:
局部禁用:
当全局已经配置,局部想要限制的话,可以直接局部限制,也就是上述的局部使用
如果不配置:
有默认格式,解析方面:三种编码都能解析,响应方面:浏览器访问看到浏览器的样子,postman访问看到json格式
注意:使用 BrowsableAPIRenderer要记得注册,这样才会显示页面
不注册就会报错
基于API写接口
from rest_framework.views import APIView
视图类
from rest_framework.views import APIView from .models import Book from .serializer import Bookserializer class BookView(APIView): def get(self,request): book_list = Book.objects.all() rse = Bookserializer(book_list,many=True) return Response({'code':111,'msg':'查询成功','defult':rse.data}) def post(self,request): rse = Bookserializer(data=request.data) if rse.is_valid(): rse.save() return Response({'code':200,'msg':'添加成功','defult':rse.data}) else: return Response({'code':201,'msg':'添加失败','defult':rse.errors}) class BookDetialView(APIView): def get(self,request,pk): book = Book.objects.filter(pk=pk).first() res = Bookserializer(book) return Response({'code': 111, 'msg': '查询成功', 'defult': res.data}) def put(self,request,pk): book = Book.objects.filter(pk=pk).first() res = Bookserializer(instance=book,data=request.data) if res.is_valid(): res.save() return Response({'code':200,'msg':'修改成功','defult':res.data}) else: return Response({'code': 201, 'msg': '添加失败', 'defult': res.errors}) def delete(self,request,pk): book = Book.objects.filter(pk=pk).delete() return Response({'code': 111, 'msg': '删除成功'})
序列化类
from .models import Book from rest_framework import serializers class Bookserializer(serializers.ModelSerializer): class Meta: model = Book fields = ['name','price','publish','author','publish_detial','author_dic'] extra_kwargs ={ 'publish': {'write_only': True}, 'author': {'write_only': True} } #反序列化,写入的数据 #序列化,显示出去的数据,在模型层的数据 publish_detial = serializers.DictField(read_only=True) author_dic = serializers.ListField(read_only=True)
模型层
from django.db import models # Create your models here. class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField() publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE) author = models.ManyToManyField(to='Author') def publish_detial(self): return {'name':self.publish.name,'addr':self.publish.addr} def author_dic(self): #作者表是一个列表 l = [] for author in self.author.all(): l.append({'name':author.name,'age':author.age,'sex':author.get_sex_display()}) return l class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) class Author(models.Model): sex_choice =[(1,'男'),(2,'女'),(3,'未知')] name = models.CharField(max_length=32) age = models.IntegerField(default=18) sex = models.IntegerField(choices=sex_choice,default=1)
视图类封装
GenericAPIView 有类属性和方法
重要属性:
-queryset:以后放所有某个表查询出的数据
-serializer_class:要序列化的类
重要方法:
-get_queryset :要序列化的所有数据,qs对象
-get_serializer :序列化类
-get_object :修改,查询的单条
了解属性:
-lookup_field = 'pk' 路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,但是一般不改
-filter_backends:后面详细讲 过滤 功能
-pagination_class :后面详细讲 分页
了解方法:
-get_serializer_class 后期咱们可能会重写它,指定某些方法使用不同的序列化类
-filter_queryset 后面跟过滤功能一起讲
以下代码为视图类:
#封装 class GenericAPIView(APIView): queryset = None serializer_class = None # 查找全部 def get_queryset(self): return self.queryset.all() #序列化 def get_serializer(self,*args,**kwargs): return self.serializer_class(*args,**kwargs) #获取单条数据 def get_object(self,pk): res = self.get_queryset() return res.filter(pk=pk).first()
class BookView(GenericAPIView): queryset = Book.objects #即使这里加了all,后续查询所以也需要加,所以在封装的get_queryset中有all serializer_class = Bookserializer def get(self,request): query_list = self.get_queryset() res = self.serializer_class(query_list,many=True) return Response({'code': 111, 'msg': '查询成功', 'defult': res.data}) def post(self,request): res = self.serializer_class(data=request.data) if res.is_valid(): res.save() return Response({'code': 200, 'msg': '添加成功', 'defult': res.data}) else: return Response({'code':201,'msg':'添加失败','defult':res.errors}) class BookDetialView(GenericAPIView): queryset = Book.objects # 即使这里加了all,后续查询所以也需要加,所以在封装的get_queryset中有all serializer_class = Bookserializer def get(self,request,pk): obj = self.get_object(pk) res = self.serializer_class(obj) return Response({'code': 111, 'msg': '查询成功', 'defult': res.data}) def put(self,request,pk): obj = self.get_object(pk) res = self.serializer_class(instance=obj,data=request.data) if res.is_valid(): res.save() return Response({'code': 200, 'msg': '修改成功', 'defult': res.data}) else: return Response({'code': 201, 'msg': '修改失败', 'defult': res.errors}) def delete(self,request,pk): self.get_object(pk).delete() return Response({'code': 200, 'msg': '删除成功'})
关于一些错误
错误一:
一定要用在数据的时候再查:
def get_queryset(self):
return self.queryset.all()
GenericAPIView,
RetrieveModelMixin:查询一条
retrieve---》代码就是和之前写获取单条get方法内容一样
CreateModelMixin : 新增一条
create---》代码就是和之前写新增一条 post 方法内容一样
DestroyModelMixin:删除一条
destroy---》代码就是和之前写删除一条 delete 方法内容一样
ListModelMixin:查询所有
list---》代码就是和之前写删除一条 get 方法内容一样
UpdateModelMixin
update---》代码就是和之前写删除一条put 方法内容一样
#写五个接口,而不封装成两个接口的原因是因为后期不一定5个接口都写,可能只使用其中几个
以下代码为视图类
from rest_framework.mixins import RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, ListModelMixin, \ UpdateModelMixin from rest_framework.generics import GenericAPIView class BookView(GenericAPIView, ListModelMixin, CreateModelMixin): queryset = Book.objects.all() serializer_class = Bookserializer def get(self, request): return self.list(request) def post(self, request, *args, **kwargs): return self.create(request) class BookDetialView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin): queryset = Book.objects.all() serializer_class = Bookserializer def get(self, request, pk): return self.retrieve(request, pk) def put(self, request, pk): return self.update(request, pk) def delete(self, request, pk): return self.delete(request, pk)
补充:
关于模型的类似于性别这种以数字代替文字,但读取时要以文字读取出来
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能