drf03--请求与响应、view视图组件

昨日回顾

1 序列化类之Serializer(跟表模型没有必然联系)
    -写出要序列化的字段(尽量跟模型表的字段类对应)
    -source属性(用的很少)
2 字段类
    -CharField
    -IntegerField
3 字段参数
    -通用
    	-read_only
        -write_only
    -独有
4 必须重写create和update方法
5 局部,全局钩子函数(反序列化,验证数据)
    -validate_字段名(self,item):
        校验通过,直接return,校验失败,抛异常
    -validate(self,attrs)
    	校验通过,直接return attrs,校验失败,抛异常
        
5 序列化类之ModelSerializer(跟表模型没有必然联系)
    -写一个内部类  
    -class Meta:
        model=表模型
        fields=['字段','方法']
        extra_kwargs={'name':{}}
   -重写要序列化的字段字段
   -要序列化的字段,类是通过表模型映射过来的
6 ModelSerializer不需要重写create和update(ModelSerializer帮我们写了)

7 指定某个字段序列化的格式(两种方法)
    -在表模型中写方法(包装成数据属性)
    -在序列化类中使用SerializerMethodField

今日内容

1.请求与响应(**)

1.drf的请求

# Request类的对象 方法
    -.data:包含了对POST、PUT、PATCH请求方式解析后的数据
    -.query_params:Django标准的request.GET
    
# 通过配置,设置后端接口支持的编码格式
    # 默认情况支持三种
    -全局配置(在项目的settings.py中)
    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',  # json
            # 'rest_framework.parsers.FormParser',  # urlencoded
            # 'rest_framework.parsers.MultiPartParser'  # form-data文件格式
        ]
    }
    -局部配置(在视图类中写类属性)
        class IndexView(APIView):
            parser_classes = [JSONParser,] # 只支持json格式
    
# 查找顺序是先找视图类局部----》项目配置文件中----》drf的配置文件
    
     
# drf有内置的配置文件,在drf源码的settings.py中有个DEFAULT字典‘

# 默认解析的编码格式
'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser', # json
        'rest_framework.parsers.FormParser', # urlencoded
        'rest_framework.parsers.MultiPartParser' # form-data文件格式
    ]

2.响应

# drf的Response类的对象(继承了HttpResponse)
# response对象的属性 (参数)
    - data:要返回的数据,放到了http响应的响应体中
    - status:http响应的状态码
    	- drf把所有的状态码都定义成了常量 (在rest_framework.status中)
        - 在rest_framework.status中
    - headers: http响应头,是个字典
    	- {'name':'lqz'}
    - content_type: 响应编码格式,了解 例:'application/json'、 'text/html'
    
    
# 响应显示的格式的局部配置和全局配置
    -全局配置(在项目的settings.py中)
    REST_FRAMEWORK = {
      'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
    }
    -局部配置(在视图类中写类属性)
        class IndexView(APIView):
    		renderer_classes = [JSONOpenAPIRenderer,]

2.视图组件之两个视图基类(*****

1.APIView

# 第一层:继承APIView完全自己写
class BookView(APIView):
    def get(self, request):
        qs = Book.objects.all()
        ser = serializer.BookSerializer(instance=qs, many=True)
        return Response(data=ser.data, status=200)

    def post(self, request):
        ser = serializer.BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '创建成功'})
        else:
            return Response(data=ser.errors)

class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = serializer.BookSerializer(instance=book)
        return Response(data=ser.data, status=200)

    def put(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = serializer.BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '修改成功'})
        else:
            return Response(data=ser.errors)

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response(data={'code': 100, 'msg': '删除成功'})

# models.py
class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.CharField(max_length=32)
    
# ser.py
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields='__all__'

2.GenericAPIView

# 第二层:继承GenericAPIView   Generic: adj. 通用的

from rest_framework.generics import GenericAPIView   # 也是继承于APIView

1. 两个类属性
    queryset = Book.objects.all()  # 要序列化的数据对象( 可以不用.all(),内部get_queryset方法 自动.all() )
    serializer_class = serializer.BookSerializer # 要使用的序列化类
    
2.三个方法
    get_queryset() # 获取要序列化的多条数据对象
    get_serializer() # 获取要使用的序列化类
    get_object()    # 获取要序列化的单条数据对象(查找条件:一定要用pk,如果你想改,重写类属性lookup_field)


class BookView(GenericAPIView):
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = serializer.BookSerializer  # 要使用的序列化类

    def get(self, request):
        qs = self.get_queryset()  # GenericAPIView提供的 等同于self.queryset
        ser = self.get_serializer(instance=qs, many=True)  # GenericAPIView提供的 等同于self.serializer_class
        return Response(data=ser.data, status=200)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '创建成功'})
        else:
            return Response(data=ser.errors)


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()  
    serializer_class = serializer.BookSerializer  

    def get(self, request, *args, **kwargs):
        book = self.get_object()  
        ser = self.get_serializer(instance=book)
        return Response(data=ser.data, status=200)

    def put(self, request, pk):
        book = self.get_object()
        ser = self.get_serializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '修改成功'})
        else:
            return Response(data=ser.errors)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response(data={'code': 100, 'msg': '删除成功'})

3.视图组件之5个视图扩展类(*****

# 第三层:继承GenericAPIView + 5个视图扩展类(不是视图类,没有继承APIView及其子类)
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

from rest_framework.generics import GenericAPIView


class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Book.objects.all() 
    serializer_class = serializer.BookSerializer

    def get(self, request):
        # qs = self.get_queryset()  
        # ser = self.get_serializer(instance=qs, many=True)
        # return Response(data=ser.data, status=200)
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookDetailView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Book.objects.all() 
    serializer_class = serializer.BookSerializer 

    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)
    
# 小技巧:五个接口需要使用的方法名字 和 类名前面部分中 一一对应
1. 查所有  list
2. 增一个  create

3. 查一个  retrieve
4. 改一个  update
5. 删一次  destroy

4.视图组件之9个视图子类(*****

# 第4层:9个视图子类   # 实际开发,使用这种较多  因为还需要自己额外写一些业务逻辑,通常就是通过重写方法

# 分别是: 五个接口 + 其的组合
6. 查所有+增     ListCreate
7. 查一个+改     RetrieveUpdate
8. 查一个+删     RetrieveDestroy
9. 查一个+改+删  RetrieveUpdateDestroy

from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveUpdateAPIView, \
    RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView


# ListAPIView 就是继承 GenericAPIView + ListModelMixin

class BookView(ListCreateAPIView):
    queryset = Book.objects.all() 
    serializer_class = serializer.BookSerializer  


class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()  
    serializer_class = serializer.BookSerializer  

5.视图组件之视图集(*****

5.1基本使用

# 第5层:继承视图集
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = serializer.BookSerializer
    
# 继承ModelViewSet的路由写法: (路由必须指定 actions)
path('books/', views.BookView.as_view(actions={'get':'list','post':'create'})), 
path('books/<int:pk>', views.BookView.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

5.2源码分析:ViewSetMixin类

# ViewSetMixin类 重写了as_view()

# 请求来了,路由匹配成功会执行 ViewSetMixin.as_view()内部里的view()

@classonlymethod
def as_view(cls, actions=None, **initkwargs):
    def view(request, *args, **kwargs):
        # 核心代码(所以路由中只要配置了对应关系,比如{'get':'list'}),当get请求来,就会执行list方法
        for method, action in actions.items():  # method:get   action:list        
            handler = getattr(self, action)  # self就是视图类,去视图类中反射list  
            setattr(self, method, handler)  # 通过反射往视图类中写入 self.get=list
	return csrf_exempt(view)
    
# 作用:
    使用ViewSetMixin类及其子类时,可在路由匹配时中,为 某个请求方式 指定 特定的视图接口
    # 注意:1. 路由就必须指定actions参数  视图接口名就可以随意写,只要actions映射好就行
    # 	   2. 使用ViewSetMixin类及其子类,一定要放在APIVIew前 (执行左继承的as_view)


    
# 例:指定 get请求 对应 get_all_book接口
# views.py  
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): 
    def get_all_book(self,request):
        print("xxxx")
        book_list = Book.objects.all()
        book_ser = BookSerializer(book_list, many=True)
        return Response(book_ser.data)
    
# urls.py
    path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),

5.3其他子类

-ViewSetMixin: 路由可指定actions参数  .as_view(actions={'get':'方法'})

-ViewSet:             ViewSetMixin+APIView  (作用:就是在基础的APIview上,可指定actions参数)
-GenericViewSet:      ViewSetMixin+GenericAPIView  (作用:就是在基础的Genericview上,可指定actions参数)
-ModelViewSet:        ViewSetMixin+GenericAPIView+视图扩展类   (就是表五个接口都有)
-ReadOnlyModelViewSet:ViewSetMixin+GenericAPIView+ListModelMixin+RetrieveModelMixin  (只读接口:查所有和查一个)

补充

1.在pycharm中查看类的继承关系

2.继承关系图

作业

# 作业一 
1.两个视图基类
2.5个视图扩展类
3.9个视图子类
4.视图集的所有类
继承关系画出来,写出每个类中常用的方法和属性

# 作业二
    -实现图书和和出版社的5个接口
    -配置返回数据格式只能是json,只能解析json

# 作业三
1.什么是正向代理,什么是反向代理
posted @ 2021-11-26 00:32  Edmond辉仔  阅读(50)  评论(0编辑  收藏  举报