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

视图类中的ser.is_valid(),就会执行校验 校验通过返回True 不通过返回Flase

is_valid()

入口:
'''
ser.is_valid()是序列化类的对象 就假设序列化类是假设序列化类是BookSerializer -- 找is_valid() 
没有--去ModelSerializer里找 
没有--去父类Serializer里找
没有--去父类BaseSerializer中找--找到了
'''
   def is_valid(self, *, raise_exception=False):
        if not hasattr(self, '_validated_data'):
            #首次判断self里有没有_validated_data 没有直接走try
            try: 
                self._validated_data = self.run_validation(self.initial_data)
            #首次 self序列化类的对象 属性中没有_validation 一定会走这句【核心】走过就有了 以后再来不走
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)
            #如果raise_exception是True 就会抛异常 统一处理 返回信息

        return not bool(self._errors)
    
self._validated_data = self.run_validation(self.initial_data)
#一定不要直接摁ctrl点进去
'''
这里的self是序列化类BookSerializer的对象 
找run_validation切记不是直接ctrl点进去查看 
要从自身开始找顺序是先在BookSerializer里找
没有--去父类 ModelSerializer里找
没有--去父类Serializer里找--找到了
而不是直接点进去 查看的是Field中的run_validation
''''
raise_exception=True 校验没通过会直接抛异常就不用if判断了  

run_validation()

    def run_validation(self, data=empty):
        (is_empty_value, data) = self.validate_empty_values(data)
        #字段自己的和validates方法
        if is_empty_value:
            return data
        value = self.to_internal_value(data)
        #局部钩子
        try:
            self.run_validators(value)
            value = self.validate(value)
            #全局钩子 --- 如果在BookSerializer中写了validate,优先走他
        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
        for field in fields:
            validate_method = getattr(self, 'validate_' + field.field_name, None)
           #self BookSerializer的对象 反射validate_name
            try:
            	validated_value = validate_method(validated_value)
                 #在执行BookSerializer类中的validate_name方法 传入了要校验的数据 validated_value就是name参数
            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 有什么用?  断定你是不是xxx 不是就直接抛异常

if判断:
#	name = 'lqz'

# if name == 'lqz':
#     print('对了')
# else:
#     # print('错了')
#     raise Exception('名字不为lqz,不能继续走了')

断言:
assert name=='xxx'
print('后续代码')
判断是不是 是走后续代码
判断不是 抛异常

drf之请求

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

方式一:在继承自APIView及其子类的视图类中配置(局部配置)
总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
    parser_classes = [JSONParser,]
    
方式二:在配置文件中配置(影响所有 全局配置)
django有套默认配置 每个项目有个配置
drf有套默认配置 每个项目也有个默认配置
 REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        # 'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        # 'rest_framework.parsers.MultiPartParser',
    ],
}
想用哪个就打开哪一个

方式三:全局配了1个 某视图类想要3个
只需要在视图类配置三个即可
因为先从视图类自身找 找不到去项目的drf配置中找 再找不到就去drf默认的配置找

2.Request类有哪些属性的方法

data  在data里面获取数据

__getattr__ 反射出老的request.method

query_params 等于 request.GET

drf之响应

1.Response能够响应的编码格式

drf 是djngo的一个app 所以要注册
drf响应 如果使用浏览器和postman访问同一个窗口 
	#drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据
     方式一:在视图类中写(局部配置)
         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',
    ],
}
    #想用哪个方式就打开哪个方式
    
    方式三:使用顺序(一般用内置的即可)
    	优先使用视图类中的配置 其次使用项目配置文件中的配置 最后使用内置的
    

2.Resposne的源码属性或方法

drf的源码分析:
	from rest_framework.response import Response
    视图类的方法返回时 return Respones 走他的__init__,__init__可以传哪些参数

	Response init可以传的参数
      def __init__(self, 
                   data=None,
                   status=None,
                   template_name=None,
                   headers=None,
                   exception=False,
                   content_type=None)
        data:
        	之前写的ser.data 可以是字典、列表或字符串 -- 序列化后返回给前端 -- 前端在响应体中看到的就是这里面的数据
        status:
        	http响应状态码 默认是200 可以自己更改 
            #drf在status包下 把所有的http响应状态码都写了一边 是常量
            #导入模块from rest_framework.status import HTTP_200_OK
        	#Response('dddd',status=status.HTTP_201_OK)
            
        template_name:
        	修改响应模板的样子 BrowsableAPIRenderer浏览器的样子是定死的 可以自己定制
        headers:
        	响应头 headers = {k:v}样式
            djgno怎么在响应头中加东西
            obj = HttpResponse('ddd')
            obj['xxx']='yyy'
            return obj
        content_type:
            响应编码格式 一般不动
            
#重点:data、status,headers

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

APIView 和 View区别
	1.传入视图类的是drf的request 不是djngo的request
    2.以后用的都是新的request
    3.全局异常捕获
    4.三大认证

两个视图基类

APIView :
    类属性: renderer_classes 响应格式
    		parser_classes	 能够解析的请求格式
        	authentication_classes 认证类
            throttle_classes 频率类
            permission_classes 权限类
            
    

1.APIView+ModelSerializer+Resposne写5个接口

第一层:初级

model.py

from django.db import models
#图书表
class Books(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField(to="Author")

 #定制写在外键所在的表下面
    def publish_dict(self):
        return {'name':self.publish.name,'add':self.publish.add}

    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name':author.name,'phone':author.phone})
        return l

#出版社表
class Publish(models.Model):
    name = models.CharField(max_length=32)
    add = models.CharField(max_length=32)

#作者表
class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=32)
    gender = models.CharField(max_length=2)


url.py

from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/',views.BooksView.as_view()),
    path('books/<int:pk>/',views.BookView.as_view())

views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
# Create your views here.
from .models import Books
from .serialize import BookSerializers
#不需要筛选条件的视图类
class BooksView(APIView):
    #获取所有图书信息
    def get(self,request):
        books = Books.objects.all()
        ser = BookSerializers(instance=books,many=True)
        return Response(ser.data)
	#新增图书信息
    def post(self,request):
        ser = BookSerializers(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':'新增成功'})
        else:
            return Response({'code':101,'msg':ser.errors})
#需要额外条件的视图类
class BookView(APIView):
    #获取某一本图书信息
    def get(self,request,pk):
        books = Books.objects.filter(pk=pk).first()
        ser = BookSerializers(instance=books)
        return Response(ser.data)
	#修改某一本图书信息
    def put(self,request,pk):
        books = Books.objects.filter(pk=pk).first()
        ser = BookSerializers(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):
        Books.objects.filter(pk=pk).first().delete()
        return Response({'code': 100, 'msg': '删除成功'})

serialize.py

from rest_framework import serializers
from .models import Books

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = Books
        fields =['name','price','publish','authors','publish_dict','author_list']
        extra_kwargs = {
            'publish':{'write_only':True},
            'authors':{'write_only':True},
        }
#用了ModelSerializer继承了Serializers 大部分请求不用写create和update 底层直接写好了 

基于GenericAPIView扩展类

属性:
	queryset:	要序列化或者反序列化的表模型数据
    serializer_class: 使用的序列化类
    lookup_field: 查询单条的路由分组分出来的字段名
    filter_backends:	过滤类的配置
    pagination_class:	分页类的配置
    
方法:
	get_queryset: 获取要序列化的对象
    get_object:   获取要序列化的单个对象
    get_serializer:获取序列化类 
    get_serializer_class:差不多 一般不调用它 重写他
    filter_queryset: 过滤有关

第二层:中级

只优化了views.py

这样的好处是 以后不管写哪一个视图类 里面的代码都不用动了

只需要更改queryset = Books.objects.all()和 serializer_class = BookSerializers即可

class BooksView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    def get(self,request):
        books = self.get_queryset()  #可以用self.queryset拿到 但不要这样用 有一个方法 可扩展性更高 后期可以重写get_queryset
        ser = self.get_serializer(instance=books,many=True) #同理 但后期重写写的是get_serializer_class 指定哪个序列化类来序列化
        return Response(ser.data)

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

class BookView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    def get(self,request,pk):
        books = self.get_object() #获取某一条 源码中定义 lookup_field = 'pk' 所以获取的参数必须是pk 可以在全局中修改
        ser = self.get_serializer(instance=books)
        return Response(ser.data)

    def put(self,request,pk):
        books = self.get_object()
        ser = self.get_serializer(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):
        self.get_object().delete()
        return Response({'code': 100, 'msg': '删除成功'})

基于GenericAPIView+5个视图扩展类

5个视图扩展类

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

CreateModelMixin:新增  -- 方法 --create
UpdateModelMixin:修改  -- 方法 --update
DestroyModelMixin:删除  -- 方法 --destroy
RetrieveModelMixin:查询单个  -- 方法 --retrieve
ListModelMixin:查询多个  -- 方法 --list

只优化了views.py

class BooksView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    def get(self,request):
       return self.list(request)

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

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