认证组件 |
使用:写一个认证类,继承BaseAuthentication
在类中写authenticate方法,把request对象传入
能从request对象中取出用户携带的token根据token判断是否登录过
如果登录过,返回两个值 user对象 ,token对象(或者其他自定义的对象)
如果没有登录过抛异常
from rest_framework.authentication import BaseAuthentication from app01 import models from rest_framework.exceptions import AuthenticationFailed class MyAuth(BaseAuthentication): def authenticate(self,request): # print(‘我是认证类中的方法,只要配置了,一定会执行‘) token = request.GET.get(‘token‘) token_obj=models.Token.objects.filter(token=token).first() if token_obj: #有值表示登录 # return #可以没有返回值它就直接接续掉这一次循环了 继续下一次循环 如果有值就解压赋值给self.user, self.auth self就是Request对象 return token_obj.user,token_obj #token_obj.user就是当前登录对象 正向查询 你就可以在任何地方调用当前登录用户了request.user 循环就直接解释了 else: #没有值表示没登录,抛异常 raise AuthenticationFailed(‘您没有登录‘)
全局使用
在settings中配置
# 全局使用认证功能 REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.MyAuths.MyAuth",]}
局部使用
在视图类中配置
authentication_classes= [MyAuth,] #认证
布局禁用
在视图类中配置
authentication_classes= []
update_or_create()有就跟新,没有就创建 查询的时候会查询k=v 有的话就把表中的{‘token‘:token}替换掉 没有就创建一条数据
参数:key=value,default={‘token‘:token}
uuid的使用:生成一个唯一的随机字符串
源码分析:
APIView中的dispatch--->slef.initial(认证,权限,频率)
--->self.perform_authentication(认证)
--->本质又调用新的reqeust对象的user方法
---->Request中进入找到user方法内部执行了self._authenticate(注意self是新的request对象)
for循环self.authenticators 对象自己的属性(for authenticator in self.authenticators)
实例化的时候是在APIView中dispatch中的
定位一下发现是继承了APIView类中去找get_authenticators方法
点位一下发现还是APIView中那么就是试图类对象调用这个方法属性查找顺序
就是我们配置在视图类中的一个认证类 列表中就是一个认证类对象
那么我们前面的for循环(for authenticator in self.authenticators)就是一个认证类对象
需要注意的是视图类中使用的认证类的时候如果第一个直接返回值这个for循环就结束了,如果视图类中的认证有多个的话后面的都不会执行了
权限 |
使用写一个权限类
from rest_framework.permissions import BasePermission class MyPermision(BasePermission): message = ‘不是超级用户,查看不了‘ #错误信息显示中文 def has_permission(self,request,view): #reques就是包装好的request,self在APIView类中就是产生的对象 view if request.user.user_type == 1: return True else:return False # "detail": "You do not have permission to perform this action."普通用户
局部使用
在视图类中配置:
permission_classes=[MyPermision,]
全局使用
在settings中配置
REST_FRAMEWORK={‘DEFAULT_PERMISSION_CLASSES‘:[‘自定义的权限类‘],}
局部禁用
在视图类中配置
permission_classes=[]
返回的提示是中文
权限类中配置 message=中文
源码分析 APIView---dispatch--initial--check_permissions
一个个权限类对象
对象调用自己方法 注释self定位一下发现是APIVeiw类中的那么self就是APIView对象写权限类的has_permission方法的时候传入request view参数
APIView调用方法 message就是错误信息抛出中文
视图 |
基本视图
路由
url(r‘^publish/$‘, views.PublishView.as_view()), url(r‘^publish/(?P<pk>\d+)/$‘, views.PublishDetailView.as_view()),
视图
class PublishSerializers(serializers.ModelSerializer): class Meta: model=models.Publish fields=‘__all__‘ class PublishView(APIView): def get(self, request): publish_list = models.Publish.objects.all() bs = PublishSerializers(publish_list, many=True) # 序列化数据 return Response(bs.data) def post(self, request): # 添加一条数据 print(request.data) bs=PublishSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return Response(bs.data) else: return Response(bs.errors) class PublishDetailView(APIView): def get(self,request,pk): publish_obj=models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(publish_obj,many=False) return Response(bs.data) def put(self,request,pk): publish_obj = models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(data=request.data,instance=publish_obj) if bs.is_valid(): bs.save() # update return Response(bs.data) else: return Response(bs.errors) def delete(self,request,pk): models.Publish.objects.filter(pk=pk).delete() return Response("")
第二种视图组件mixin类和generice类编写视图
路由
url(r‘^publish/$‘, views.PublishView.as_view({‘get‘: ‘list‘, ‘post‘: ‘create‘})), url(r‘^publish/(?P<pk>\d+)/$‘,views.PublishView.as_view({‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘})),
视图
from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin from rest_framework.generics import GenericAPIView class PublishView(ListModelMixin,CreateModelMixin,GenericAPIView): queryset=models.Publish.objects.all() serializer_class=PublishSerializers def get(self, request): return self.list(request) def post(self, request): return self.create(request) class PublishDetailView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,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)
写ge和post,在其中调用父类的create或者list方法 list是获取多条
第三种视图组件使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView class PublishView(ListCreateAPIView): queryset=models.Publish.objects.all() serializer_class=PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset=models.Publish.objects.all() serializer_class=PublishSerializers
第四种视图组件使用ModelViewSet
路由
url(r‘^publish/$‘, views.PublishView.as_view({‘get‘:‘list‘,‘post‘:‘create‘})), url(r‘^publish/(?P<pk>\d+)/$‘, views.PublishView.as_view({‘get‘:‘retrieve‘,‘put‘:‘update‘,‘delete‘:‘destroy‘})),
视图
from rest_framework.viewsets import ModelViewSet class PublishView(ModelViewSet): queryset=models.Publish.objects.all() serializer_class=PublishSerializers
自定义视图方法
路由
url(r‘^aa/$‘, views.PublishView.as_view({‘get‘: ‘aaa‘})), url(r‘^bb/$‘, views.PublishView.as_view({‘get‘: ‘bbb‘})),
视图
from rest_framework.viewsets import ViewSetMixin from rest_framework.views import APIView # ViewSetMixin 重写了as_view方法 class Test(ViewSetMixin,APIView): def aaa(self,request): return Response()
ViewSetMixin重写了as_view方法,路由配置就改了,可以写成映射的形式{get:get_one}
as_view方法内部执行效果
通过反射的缺纸跟赋值,完成映射,根据请求方式执行相对应的方法(比如:get请求执行get_one方法,在路由中配置{get:get_one})
频率组件 |
使用
写一个频率类,继承SimpleRateThrottle
重写get_cache_key,返回self.get_ident(request)
一定要记住配置一个scop=‘字符串‘
第二部:在settings中配置
REST_FRAMEWORK = { ‘DEFAULT_THROTTLE_RATES‘:{ ‘lxx‘:‘3/m‘ } }
局部使用
在视图类中配置:
throttle_classes=[Throttle,]
全局使用
在settings中配置
REST_FRAMEWORK={‘DEFAULT_THROTTLE_CLASSES‘:[‘自己定义的频率类‘],}
局部禁用
在视图类中配置
throttle_classes=[]
原文地址:https://www.cnblogs.com/lakei/p/11135367.html