首页 > 其他分享 >drf从入门到飞升仙界 05

drf从入门到飞升仙界 05

时间:2023-02-05 20:12:07浏览次数:37  
标签:ser return 仙界 05 self request 视图 data drf

反序列化类校验部分源码解析

# 反序列化校验,什么时候开始执行校验
    视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回false
# 反序列化类校验的入口: ser.is_valid()
    ser.is_valid()是序列化类的对象,假设序列化类是BookSerializer
    ---》is_valid---》找不到,找到父类BaseSerializer中有 :【 raise_exception:先注意】
     def is_valid(self, *, raise_exception=False):
    
        if not hasattr(self, '_validated_data'):
            try:
                # self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
                self._validated_data = self.run_validation(self.initial_data)
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)
# self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象
    -切记一定不要按住ctrl键点击
    -真正的执行顺序是,从下往上找,找不到,再往上
    -最终从Serializer类中找到了run_validation,而不是Field中的run_validation
    
    
    def run_validation(self, data=empty):
        # 字段自己的,validates方法
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
        # 局部钩子----【局部钩子】
        value = self.to_internal_value(data)
        try:
            
            self.run_validators(value)
            # 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
            value = self.validate(value)
 
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))

        return value
    
# 局部钩子  self.to_internal_value(data)    ---》self是BookSerializer的对象,从根上找
     def to_internal_value(self, data):
        ret = OrderedDict()
        errors = OrderedDict()
        fields = self._writable_fields
        # fields写在序列化类中一个个字段类的对象
        for field in fields:
            # self BookSerializer的对象,反射validate_name
            validate_method = getattr(self, 'validate_' + field.field_name, None)
            try:
                # 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
               validated_value = validate_method(validated_value)
            except ValidationError as exc:
                errors[field.field_name] = exc.detail
          
            else:
                set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise ValidationError(errors)

        return ret

断言

# 断言的关键字 
    assert   : 断定你是XX,如果不是就抛异常  
# 源码中大量使用了try和断言
# 断言的使用
name = 'tom'

# if name = 'tom': # print('对') # else: # raise Exception('名字不能是tom以外的') assert name='tom' # 断定是,不是直接抛异常 print('名字不能是tom以外的')

drf之请求

# 1.Request能够解析的前端传入的编码格式

# 方式一:继承来自APIView及其子类的视图类中配置(局部配置)
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
    # 我们所写的接口,只能接收某种编码格式,比如接收json格式
    # parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类]
    parser_classes = [JSONParser,]

    def post(self, request):
        # 请求中携带数据,都从request.data中取
        print(request.data)
        # 如果是json格式编码,request.data就是普通dict
        # 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict
        print(type(request.data))
        return Response()

# 方式二:直接在配置文件中配置(影响所有,全局配置)
    - django有套默认配置,每个项目有个配置
    - drf有套默认配置,在django的配置文件中:
       REST_FRAMEWORK = {
           'DEFAULT_PARSER_CLASSES': [
               # 'rest_framework.parsers.JSONParser',
               'rest_framework.parsers.FormParser',
               # 'rest_framework.parsers.MultiPartParser',
           ],
       }

# 方式三:全局配了一个,某个视图类需要三个,如何配置:
    - 只需要在视图类,配置三个即可
    - 因为:先从视图类自身找,找不到需要去项目drf配置中找,最后去drf默认配置中找
 

# 2.Request类有哪些属性和方法
- 视图类方法中的request
data
__getattr__
query_params

 

drf之响应

# drf 是django的一个app,所以要注册
# drf的响应,如果使用浏览器和postman访问,返回的格式不同
   - 原因是drf做了判断,对于浏览器会返回好看一些,对于postman只会返回json数据

# 方式一:在视图类中写(局部配置)
- 两个响应类--->在drf配置文件中找--->两个类   
from  rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
    # 我们所写的接口,只能接收某种编码格式,比如接收json格式
    # parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类]
    # parser_classes = [JSONParser,]

    renderer_classes = [JSONRenderer,]
    def post(self, request):
        # 请求中携带数据,都从request.data中取
        print(request.data)
        # 如果是json格式编码,request.data就是普通dict
        # 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict
        print(type(request.data))
        return Response()

# 方式二:在项目配置文件中写(全局配置)
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
        ],
    }

# 方式三:使用顺序(一般使用内置的就行)
    优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的配置

# Response源码属性和方法
   - drf源码分析
   from rest_framework.response import Response
   - 视图类的方法返回时,return Response, 走自己的__init__,
     init中可以传入的参数有:
            def __init__(self,
                               data=None,
                               status=None,
                               template_name=None,
                               headers=None,
                               exception=False,
                               content_type=None)
     data: 
         1. 之前写的ser.data 可以是字典或列表,字符串
         2. 序列化之后返回给前端
         3.前端在响应体代码中看到的就是这个data

    status:
         1.http响应的状态码,默认是200,可以改
         2.drf在status包下,把所有http响应状态码都写一遍
         3.from rest_framework.status import HTTP_200_OK
         4.Response('dddd',status=status.HTTP_200_OK)
    template_name:
         了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子
    headers:
         响应头,http响应头,如何在响应头中加东西
    content_type :
         响应编码格式,一般不动
    
"""
重点:data,status,headers
"""
    

 

视图组件介绍及两个视图基类

# drf视图类
# 1.APIVIew跟之前View区别
     - 传入到视图方法中的是REST framework和Request对象,而不是Django的HttpRequest对象:
     - 视图方法可以返回 REST framework的Response对象
     - 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
     - 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制


# 2.两个视图基类
    - APIView
        -类属性:
            renderer_classes           # 响应格式
            parser_classes             #能够解析的请求格式
            authentication_classes     #认证类
            throttle_classes           #频率类
            permission_classes         #权限类
        -基于APIView+ModelSerializer+Resposne写5个接口
               详见代码

# 3.视图类
from .models import Book
from .serializer import BookSerializer


class BookView(APIView):
    def get(self, request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            # 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
            return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})


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

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

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


# 4.序列化类
### ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

# 5.路由
urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

 

基于GenericAPIView+5个视图扩展类

# 1.视图类
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    ListModelMixin


# 基于GenericAPIView+5个视图扩展类写接口

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

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

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


class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = 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)

# 2.序列化类
class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

# 3.路由
class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

 

标签:ser,return,仙界,05,self,request,视图,data,drf
From: https://www.cnblogs.com/juzijunjun/p/17093871.html

相关文章