一、ModelSerializer补充
二、序列化类校验源码分析(了解)
三、断言———assert
断言的定义:断言,作用的判断,断定一个变量必须是xx,如果不是就报错
#assert的断言用法
name='主啊'
assert name =='主啊','name必=须等于xf' #后半部分是抛的异常
# 其实就是If 和抛异常
断言如果校验通过才会走之后的代码,不然就抛出异常停止了
四、drf之请求
Request能够解析的前端传入的编码格式
因为我们通过打印前端通过三种方法传过来数据,发现Json格式是标准的dict,剩下两种是QueryDict的数据类型,虽然用法一致,但是其实不是一个类型的东西
现在有一个需求,需求是该接口只能接收json格式,不能接收其他格式
1.第一种方法
在继承自APIView及其子类的的视图类中配置(局部配置)
# 要先导入,总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,] # 这个属性是能够解析前端传入的什么编码格式,一个列表的形式
2.第二种,去看一下drf的settings.py配置,注意不是django的哦,然后把这个复制到djaong的配置文件中,新增一个REST_FRAMEWORK的配置(全局配置)
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
# 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser',
],
}
3. 第三种,局部配了,全局也配了,drf的源码没动,到底是按谁的来呢?
自己说了算,就是局部为大
五、drf之响应
经过研究,我们不用postman,用浏览器去打开我们的api,发现报错!按道理是没问题的,但是为啥报错,因为我们drf要去注册一下
'rest_framework', # 注册一下即可
注册后打开了页面,发现页面长的还挺不错,这是因为基于drf的响应,如果使用浏览器和postman访问同一个接口,返回格式是不一样的,drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据。
响应的编码格式的变更
其实和请求那三个方法也是一样的
# 方式一:在视图类中写(局部配置)
-两个响应类---》找---》drf的配置文件中找--》两个类
导一下
-from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes=[JSONRenderer,]
# 方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
# 方式三:使用顺序(一般就用内置的即可)
优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的
Response源码分析
点进去看,先试试看到头,发现继承的最头头是HttpResponseBase,所以他能返回字符串
def __init__(self, data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
再研究这些参数
data就是ser.date(前面我们自己写过的)
status:http响应的状态码,默认是200,可以在Resposne()的括号内添加status=xxx来改,其实drf在status包下,把所有http响应状态码都写了一遍,我们也可以这样用
from rest_framework.status import HTTP_200_OK # 导一下
Response('hahaha',status=status.HTTP_200_OK) # 这样以后改几百个状态码就能一次改定
template_name=None 浏览器的响应编码,以后可以根据公司需求自己定制
headers 可以给响应头添加数据,用于后来学习跨域(前后端分离一定会有跨域)
Response(headers={'hh':'xixi'})
六、视图组件、两个视图基类(重要)
1.两个基类
APIVIEW————drf提供的最顶层的类
GenericAPIView————继承了APIVIEW,添加了一些方法属性的类
2.基于APIVIEW + ModelSerializer +Response 快速写五个接口
class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'authors_detail', 'publish', 'authors']
extra_kwargs = {
'publish_detail': {'read_only': True},
'authors_detail': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
class BookView(APIView):
def get(self, request):
book = Book.objects.all()
ser = BookSerializers(instance=book, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializers(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 1000, 'msg': '新增成功'})
else:
return Response({'code': 1001, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
if book:
ser = BookSerializers(instance=book)
return Response(ser.data)
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
# 这里可以加点判断,我就不写了
ser = BookSerializers(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response({'code': 1000, 'msg': '修改成功'})
else:
return Response({'code': 1001, 'msg': ser.errors}, headers={'hh': 'xixi'})
def delete(self, instance, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 1000, 'msg': '删除成功'})
3.方便之处
我们按上面的方法常规写接口,如果又要写Publish的五个接口,代码基本是一样的,改改要对应的模型表,对应的序列化类而已,代码重复太多,所以有了GenericAPIView,是框架的大佬们写的
4.基于GenericAPIView+ModelSerializer +Response 写五个接口
首先导入一下
from rest_framework.generics import GenericAPIView
class BookView(GenericAPIView):
queryset = Book.objects 这是指定表模型数据可以不点all()
serializer_class = BookSerializers 这是指定用的序列化类
def get(self):
obj = self.get_queryset()
ser = self.get_serializer(instance=obj, many=True)
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 1000, 'msg': '新增成功'})
else:
return Response({'code': 1001, 'msg': ser.errors})
class BookDetailView(GenericAPIView):
queryset = Book.objects
serializer_class = BookSerializers
def get(self,request,pk):
obj = self.get_object()
ser = self.get_serializer(instance=obj)
return Response(ser.data)
def put(self,request,pk):
obj = self.get_object()
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 1000, 'msg': '修改成功'})
else:
return Response({'code': 1001, 'msg': ser.errors})
def delete(self, instance, pk):
self.get_object().delete()
return Response({'code': 1000, 'msg': '删除成功'})
总结:
1.需要指定两个属性用来表示要用的表和序列化类
还有其他属性:
lookup_field = 'pk' 路由有名分组分出来的字段名
2.self.queryset() 可以优化成self.get_queryset()
这是开发者的高阶编程思想做的优化,我们这样就可以在类中重写方法做拓展
3.同理,做序列化时也是,self.get_serializer(),这样是方便以后同一个视图函数,做不同功能时,需要不同的序列化类时,可以通过重写get_serializer 里面的get_serializer_class方法来重新指定序列化类
4.获取单条模型对象数据,GenericAPIView给的方法是get_object(),通过查看GenericAPIView的源码,发现是根据lookup_field = 'pk' 这个东西来做筛选,这个要和路由层的有名分组的名字一致,如果不一致,在该类中重写
5.剩下的就是依样画葫芦
6.发散思考,如果再写Publish的五个接口,只有每个类开头的属性有区别,但是其他代码又重复度非常高,能不能在封装?
5.五个视图类
drf封装了五个视图拓展类,就是普通的类,封了增删改查一个查所有五个方法,必须配合GenericAPIView一起使用才行
如何使用:
导入一下
from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin
"""
ListModelMixin: 查所有
RetrieveModelMixin:查单条
CreateModelMixin:新增
UpdateModelMixin:更新
DestroyModelMixin:删除
"""
6.基于GenericAPIView+5个视图拓展类 写接口(重要)
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookSerializers
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):
queryset = Book.objects
serializer_class = BookSerializers
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
今日单词
parser_ckasses 解析方式
queryset 在GenericAPIView中是指定模型表
今日疏忽
1.基于GenericAPIView+5个视图拓展类 写接口时,用视图拓展类的方法时,忘记传request进去!
标签:GenericAPIView,return,ser,get,self,request,视图,Response,drf
From: https://www.cnblogs.com/wznn125ml/p/17094105.html