首页 > 其他分享 >drf day05 drf请求、响应编码格式,GenericAPIView以及五个视图拓展类

drf day05 drf请求、响应编码格式,GenericAPIView以及五个视图拓展类

时间:2023-02-05 22:33:53浏览次数:33  
标签:GenericAPIView return ser get self request 视图 Response drf

一、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的源码没动,到底是按谁的来呢?
	自己说了算,就是局部为大

image-20230203165930222

五、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

相关文章