RestFramework的其他组件(三)
1.认证组件
说明:认证组件就是判断用户是不是登陆状态
#代码: #首先登陆 views.py class Login(APIView): res_msg = {"code":None,"userinfo":None,"token":None,"msg":None} def post(self,request): username = request.data.get('username') password = request.data.get('password') user_obj= models.User.objects.filter(username=username,password=password).first() if user_obj: random_str = uuid.uuid4() models.UserToken.objects.update_or_create( user=user_obj, defaults={ 'token':random_str, } ) self.res_msg["code"] = 0 self.res_msg["userinfo"] = username self.res_msg["token"] = random_str self.res_msg["msg"] = '登陆成功' else: self.res_msg["code"]=1 self.res_msg["msg"] = "登陆失败" return Response(self.res_msg) from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication class UserAuthToken(BaseAuthentication): def authenticate_header(self,request): pass def authenticate(self,request): token = request.query_params.get('token') token_obj = models.UserToken.objects.filter(token=token).first() print(token_obj) if token_obj: return token_obj.user,token else: raise AuthenticationFailed('认证失败')
认证组件的使用:
class AuthorHandel(ModelViewSet): authentication_classes =[UserAuthToken,] queryset = models.Author.objects.all() serializer_class = AuthorSerializer
配置为全局的认证组件:
app01\utils\auth.py #写入: from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication from app01 import models class UserAuthToken(BaseAuthentication): def authenticate_header(self, request): pass # authenticate方法固定的,并且必须有个参数,这个参数是新的request对象,不信,看源码 def authenticate(self, request): token = request.query_params.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if token_obj: return token_obj.user,token else: raise AuthenticationFailed('认证失败')
views.py from app01.utils.auth import UserAuthToken class PublishHandel(ModelViewSet): authentication_classes = [UserAuthToken, ] # 处理认证的 permission_classes = [UserPer, ] # 处理权限的 queryset = models.Publish.objects.all() serializer_class = PublishSerializer
settings.py REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.utils.auth.UserAuthToken",] , #里面是路径字符串 "DEFAULT_THROTTLE_RATES":{ "xxx":"5/m", } }
2.权限组件
说明:权限组件就是判断用户有没有权限访问
代码: views.py from rest_framework.permissions import BasePermission class UserPer(BasePermission): message = "SVIP才能访问!" #view 代表在view组件里面使用UserPer nameview就是那个view # request 只有通过认证之后才可以使用权限组件,因为认证过后会对request重新封装 def has_permission(self, request,view): #print(request.user.usertype) if request.user.usertype == 3: return True # 通过权限 return False # 没有通过
权限组件的使用:
#那么那个view 就是PublishHandel class PublishHandel(ModelViewSet): authentication_classes = [UserAuthToken, ] # 处理认证的 permission_classes = [UserPer, ] # 处理权限的 queryset = models.Publish.objects.all() serializer_class = PublishSerializer
3.频率限制组件
说明:就是控制用户访问的频率,可以防止恶意攻击,可以简单的防止爬虫
第一种,重写限制频率的代码: views.py from rest_framework.throttling import BaseThrottle, SimpleRateThrottle import time visit_record = {} class VisitThrottle(BaseThrottle): # 限制访问的时间 VIST_TIME = 10 VISIT_COUNT = 3 def allow_request(self, request, view): id = request.META.get('REMOTE_ADDR') self.now = time.time() if id not in visit_record: visit_record[id] = [] self.history = visit_record[id] while self.history and self.now - self.history[-1] > self.VIST_TIME: self.history.pop() if len(self.history) >= self.VISIT_COUNT: return False else: self.history.insert(0, self.now) return True def wait(self): return self.history[-1] + self.VIST_TIME - self.now
使用频率限制组件
class BookHandel(ModelViewSet): throttle_classes = [VisitThrottle,] # 处理频率的 queryset = models.Book.objects.all() serializer_class = BookSerializer
第二种: 直接使用提供的简单的频率限制组件: from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = 'xxx' // 这个就是一个名字 在setting文件里面配置是需要指定这个名字找到 def get_cache_key(self, request, view): return self.get_ident(request) settings.py 文件里面写入: REST_FRAMEWORK ={ "DEFAULY_THROTTLE = { 'xxx':'5/m' # 对应上面的scope 5/m 限制每分钟访问5次 } }
4.URL生成器
URL生成器的使用:
urls.py
router = routers.DefaultRouter() router.register('authors',views.SAuthorHandle) urlpatterns = [ url(r'^', include(router.urls)), ]
使用这个生成器的缺陷:
只能使用views.py 这种形式:
class AuthorHandel(ModelViewSet): authentication_classes = [UserAuthToken, ] queryset = models.Author.objects.all() serializer_class = AuthorSerializer
5.分页组件
分页组件的使用:配置全局的 #引入分页 from rest_framework.pagination import PageNumberPagination class BookView(APIView): # 通过源码看,认证类的查找过程,和解析组件的查找过程是一样的 # authentication_classes = [UserAuth,] # throttle_classes = [VisitThrottle,] def get(self,request): ''' 查看所有书籍 :param request: :return: ''' book_obj_list = models.Book.objects.all() #创建分页器对象,PageNumberPagination类中除了PAGE_SIZE属性之外,还有个page属性,这个page属性是第几页,用法是http://127.0.0.1:8000/books/?page=1 pnb = PageNumberPagination() #通过分页器对象的paginate_queryset方法进行分页, paged_book_list = pnb.paginate_queryset(book_obj_list,request,) #将分页的数据进行序列化 s_books = BookSerializers(paged_book_list,many=True) return Response(s_books.data)
settings.py 文件的配置 REST_FRAMEWORK={ # "DEFAULT_THROTTLE_RATES":{ # "visit_rate":"5/m", # }, 'PAGE_SIZE':5, #这是全局的一个每页展示多少条的配置,但是一般不用它,因为不用的数据展示可能每页展示的数量是不同的 }
非全局的使用: #引入分页 from rest_framework.pagination import PageNumberPagination class MyPagination(PageNumberPagination): page_size = 3 #每页数据显示条数 page_query_param = 'pp' #http://127.0.0.1:8000/books/?pp=1,查询哪一页的数据 page_size_query_param = 'size' #如果我们显示的一页数据不够你用的,你想临时的多看展示一些数据,可以通过你设置的这个page_size_query_param作为参数来访问:http://127.0.0.1:8000/books/?pp=2&size=5 #那么你看到的虽然是第二页,但是可以看到5条数据,意思是将page_size的数字临时扩大了,每页展示的数据就多了或者少了,看你的page_size_query_param设置的值 max_page_size = 10 #最大每页展示多少条,即便是你前端通过page_size_query_param临时调整了page_size的值,但是最大也不能超过我们设置的max_page_size的值 class BookView(APIView): def get(self,request): ''' 查看所有书籍 :param request: :return: ''' book_obj_list = models.Book.objects.all() pnb = MyPagination() paged_book_list = pnb.paginate_queryset(book_obj_list,request,) s_books = BookSerializers(paged_book_list,many=True) return Response(s_books.data)
在继承了ModelViewSet的写法: #引入分页 from rest_framework.pagination import PageNumberPagination class MyPagination(PageNumberPagination): page_size = 3 page_query_param = 'pp' # 默认是page 在url上输入时的填写的参数 page_size_query_param = 'size' max_page_size = 10 class BookHandel(ModelViewSet): # renderer_classes = [] # 处理响应的 authentication_classes = [UserAuthToken, ] # 处理认证的 permission_classes = [UserPer, ] # 处理权限的 # parser_classes = [] # 将来在自己的写的视图类里面会加很多的类属性 # # 这些来属性就是那些组件对应的内容 throttle_classes = [VisitThrottle,] # 处理频率的 queryset = models.Book.objects.all() serializer_class = BookSerializer pagination_class = MyPagination # 配置我们自己写的分页类