drf请求和响应、2基类、5个视图扩展类、9个视图子类

一、drf 之请求

1、drf 之请求Request类

视图类继承APIView后多了
-0 去除了csrf认证
-1 新的request
   -request.data
   -request.query_params
   -request.其他跟之前一样
   -request._request  是老的
-2 三大认证
-3 全局异常

2、控制前端请求的编码格式

JSONParser:  解析json格式

FormParser: 默认的编码 urlencoded

MultiPartParser: 传文件格式 form-data 

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer

局部限制

写一个类属性 parser_classes = [JSONParser或者FormParser、MultiPartParser] 

class BookView(APIView):
    # 类属性
    parser_classes = [JSONParser]

    def get(self, request):
        res = Response(data={123}, status=500, headers={'xxx': 'yyy'})
        print(res.data)
        return res

    def post(self, request):
        print(self.parser_classes)
        print(request.data)
        return Response('新增')

效果:

全局限制

REST_FRAMEWORK = {
#####请求体的限制
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        # 'rest_framework.parsers.MultiPartParser'
    ],
#####响应格式的限制
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

补充:

全局使用后,局部再限制---》只需要在视图类上加即可

全局如果用了,局部这样配,优先用局部的,也就是这个类管理的接口,只能接收form-data格式 parser_classes = [MultiPartParser]

二、drf之响应

1、drf之Response对象源码

# from rest_framework.response import Response
### __init__ 中需要传这几个参数,不传也可以
data=None   # 字典,列表,字符串,空赋值给它---》http响应体中 ---》第一个参数是它
status=None, # http响应状态码,默认是200,千万不能写成1xx
headers=None, # http响应头,后期我们可以往响应头中放数据

content_type=None # 响应编码格式(不用管,用浏览器访问就是:text/html,用postman就是:json格式)
template_name=None   # 模版名字  默认是:rest_framework/api.html  了解,可以定制自己返回的页面样子

###补充:后面会用---》通过res.data 就能取到当时放的datga
res=Response(data={},status=500,headers={'xxx':'yyy'})
print(res.data)
return res

### 补充:取当时放的响应头
res.headers 拿不到数据,可以通过下面的方式或得到
print(res['xxx'])
print(res.has_header('zzz'))

serializer 类中序列化后的字段,通过 Response(ser.data)第一个参数赋值给data

publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)

2、drf之响应格式

响应有编码格式:默认支持json和text/html(浏览器)

# 修改只支持json

### 局部使用
class BookView(APIView):
   	renderer_classes = [BrowsableAPIRenderer]

### 全局使用
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

##局部禁用---》全局已经配置了---》局部想用浏览器的样子
class BookView(APIView):
   	renderer_classes = [BrowsableAPIRenderer]
    
# 如果不配置---》有默认
	-解析:三种编码都能解析
    -响应:浏览器访问看到浏览器的样子,postman访问,看到json格式

3、基于原生的django,向响应头写入数据

from django.http import HttpResponse

def custom_header_view(request):
    # 创建一个HttpResponse对象
    response = HttpResponse("Hello, World!")

    # 向响应头添加自定义信息
    response['X-Custom-Header'] = 'this is a test'

    return response

三、两个基类APIView和GenericAPIView

基于 GenericAPIView 写接口

使用场景: 要跟数据库打交道的接口, 普通接口使用APIview

1、GenericAPIView 源码内容

 # GenericAPIView 有类属性和方法
    	### 重要属性### 
    	-queryset:以后放所有某个表查询出的数据
        -serializer_class:要序列化的类
        
        ### 重要方法###
        -get_queryset  :要序列化的所有数据,qs对象
        -get_serializer :序列化类
        -get_object  :修改,查询的单条
        
        ## 了解类属性:
        -lookup_field = 'pk'  路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,一般不改
        -filter_backends:后面详细讲     过滤 功能
        -pagination_class :后面详细讲  分页
        
        ### 了解方法
        -get_serializer_class  后期咱们可能会重写它,指定某些方法使用不同的序列化类
        -filter_queryset 后面跟过滤功能一起讲  

补充:手写GenericAPIView

两个类属性,三个方法

class GenericAPIView(APIView):
    queryset = None
    serializer_class = None
	
    def get_queryset(self):
        return self.queryset.all()  # 真正使用的时候,再加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()

2、案例代码

view

class PublishView(GenericAPIView):
    # 定义两个类属性,方便用的时候进行替换
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request):
        obj_list = self.get_queryset()
        ser = self.get_serializer(instance=obj_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, "data": ser.data, 'msg': "添加成功"})
        else:
            return Response(ser.errors)


class PublishDetailView(GenericAPIView):
    queryset = Publish.objects.all()  # 表数据查询结果
    serializer_class = PublishSerializer  # 序列化实例

    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(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, "data": ser.data, 'msg': "修改成功"})
        return Response(ser.errors)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response('删除成功!')

注意:

-get_object方法 :修改,查询单条、删除使用

serializer

class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        # fields = '__all__'
        fields = ['name', 'addr']

四、五个视图扩展类(不是视图类)

需要先继承GenericAPIView才能使用,因为五个视图扩展类都使用了GenericAPIView中的类属性和方法

ListModelMixin :查询所有记录

CreateModelMixin:新增记录

UpdateModelMixin:修改某一条记录

DestroyModelMixin:删除某一条记录

RetrieveModelMixin:查询一条记录

1、view

from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
    RetrieveModelMixin

class PublishView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request):
        return self.list(request)

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

class PublishDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def put(self, request, pk):
        return self.update(request, pk)

    def get(self, request, pk):
        return self.retrieve(request, pk)

    def delete(self, request, pk):
        return self.destroy(request, pk)

补充:ListModelMixin 扩展类的源码,里面用到了GenericeAPIView的get_queryset()、get_serializer() 两个方法。

在视图类中 return self.list(request) 就是利用ListModelMixin 扩展类做了序列化和反序列化操作、resturn Response(serizlizer.data)

 def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

2、serializer

class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        # fields = '__all__'
        fields = ['name', 'addr']

五、九个视图子类 

1、九个视图子类分类

不带pk的

ListAPIView, CreateAPIView, ListCreateAPIView

带pk的

RetrieveAPIView, UpdateAPIView, DestroyAPIView

RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView

2、有了这九个视图子类可以大大减少代码量

导入:九个视图子类有继承 GenericAPIView,它们都可以从.generics 里导入

from rest_framework.generics import ListCreateAPIView

class PublishView(ListAPIView, ListCreateAPIView, CreateAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

class PublishDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

注:

以后想写5个接口中的某一个或某几个或所有,只需要选择继承不同的类即可,类中只需要配置两个类属性

没有继承的类相应的接口就没法使用

3、路由和序列化文件不变和之前写法一致

###路由
from django.urls import path
from app01.views import  PublishView, PublishDetailView

urlpatterns = [
    path('publishs/', PublishView.as_view()),
    path('publishs/<int:pk>', PublishDetailView.as_view()),
]

###序列化文件
class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        # fields = '__all__'
        fields = ['name', 'addr']

 

posted @ 2023-09-04 16:46  凡人半睁眼  阅读(13)  评论(0编辑  收藏  举报