序列化、认证、权限、视图回顾

回顾

基于django编写restful接口

APIView的流程分析
	重写了dispatch方法:包装了request,执行了认证,权限,频率
	

原生request对象:

​ 里面有个GET(以get形式提交的数据),以get形式提交的数据,都拆到environ内部,django把数据取出来转成了QueryDict的对象,而request.session不是原生request对象的属性,是在中间件中放进去的

drf的Request类:

​ data:post提交的数据,json格式,urlencoded,formdata编码方式的数据,data的类型并不是固定的,可能是QueryDict,也可能是字典

​ query_params:原生的GET

​ 重写了__getattr__:对象.属性,当属性不存在就会执行该方法,return getattr(self._requset,'属性'),这样就能通过封装后的request.属性也能拿到值

序列化源码分析

​ many = True的时候,生成的是列表中放了一个个序列化对象

​ many = False的时候,生成的是一个序列化对象

new__控制的:返回什么样格式的就走什么样格式的__init,比如返回的是字符串格式的就会走字符串格式的__init__,即实例化的时候就产生一个字符串

​ 校验源码部分:调用了bookser.is_valid方法才走校验,内部走了self.run_validation方法(要从根上找),在Serilaizer类中找到了run_validation方法

​ 重点:self.to_internal_value(局部钩子)/self.validate(全局钩子),Serializer类中找到了to_internal_value,去对象内部反射validate_字段名的方法,如果不为None,直接执行,于是就执行了咱们自己写的局部校验的函数

​ 序列化对象.data:执行Serializer内的data方法,又执行了父类(BaseSerializer)的data方法,执行self.to_representation(其实执行的是Serializer内的to_representation方法),最终执行的是每个字段对象的get_attribute方法,找字段对象的该方法,在Field中找到了该方法,执行了get_attribute(instance, self.source_attrs)

​ self.source_attrs:每个字段source后面指定的根据.切分后的列表(publish.name:就会被分成[publish,name]),如果是方法会执行方法,如果是字段,通过反射取出值

认证

​ 使用(必会):

​ 写一个认证类(继承BaseAuthentication)

​ 重写authenticate方法,把request对象传入

​ 能从request对象中取出用户携带的token,根据token判断是否登入,如果登入,返回两个值,user对象,token对象,如果没有登入就抛出异常raise AuthenticationFailed('您没有登录')

​ 局部使用、全局使用、局部禁用

​ update_or_create()有就更新,没有就创建models.Token.objects.update_or_create(user=user,defaults={'token':token})

​ uuid的使用:生成一个唯一的随机字符串

​ 源码分析:

​ APIVIew中的dispatch=>self.initial(认证,频率,权限)=>self.perform_authentication(认证)===>本质又调用了新的request对象的user方法

​ request.user内部执行了:self._authenticate(注意self是新的request对象),循环拿到一个个认证类的对象,执行对象的authenticate方法,传入request对象,一个个认证类的对象是在reuqest对象实例化的时候传入的,APIView中的get_authenticators,通过列表推导式生成一个个的认证类对象,然后传入request对象中

视图

基本写法:继承APIView

第二种写法

class PublishView(CreateModelMixin,ListModelMixin,GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers
    def post(self,request,*args, **kwargs):
        return self.create(request, *args, **kwargs)
    def get(self,request,*args, **kwargs):
         return self.list(request, *args, **kwargs)
        
class PublishDetailView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers
    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)

第三种写法

from rest_framework.generics import CreateAPIView,ListCreateAPIView,DestroyAPIView,RetrieveUpdateDestroyAPIView
class PublishView(ListCreateAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers

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

第四种写法

from django.views import View
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

ViewSetMixin重写了as_view方法,路由配置就改了,可以写成映射的形式{get:get_one}

as_view方法内部执行效果
通过反射的取值跟赋值,完成映射,根据请求方式执行对应的方法(比如:get请求执行get_one方法,在路由中配置{get:getone})

补充:

1.基于对象的跨表查询和基于双下划线的查询区别是什么?

​ 基于对象的跨表查询是子查询,基于双下划线是联表查询

2.left join/inner join/right join 区别是什么?

​ left join:基于左边的表连接(左表表字段齐全)

​ right join:基于右边的表连接(右表表字段齐全)

​ inner join:两张表有对应关系的连接

原文地址:https://www.cnblogs.com/yanminggang/p/11133725.html