django_rest framework 介面開發(二)
阿新 • • 發佈:2019-01-14
1 a. 認證 - 僅使用: from django.views import View from rest_framework.views import APIView from rest_framework.authentication import BasicAuthentication from rest_framework import exceptions from rest_framework.request import Requestclass MyAuthentication(object): def authenticate(self,request): token = request._request.GET.get('token') # 獲取使用者名稱和密碼,去資料校驗 if not token: raise exceptions.AuthenticationFailed('使用者認證失敗')return ("alex",None) def authenticate_header(self,val): pass class DogView(APIView): authentication_classes = [MyAuthentication,] def get(self,request,*args,**kwargs): print(request)print(request.user) ret = { 'code':1000, 'msg':'xxx' } return HttpResponse(json.dumps(ret),status=201) def post(self,request,*args,**kwargs): return HttpResponse('建立Dog') def put(self,request,*args,**kwargs): return HttpResponse('更新Dog') def delete(self,request,*args,**kwargs): return HttpResponse('刪除Dog') 梳理: 1. 使用 - 建立類:繼承BaseAuthentication; 實現:authenticate方法 - 返回值: - None,我不管了,下一認證來執行。 - raise exceptions.AuthenticationFailed('使用者認證失敗') # from rest_framework import exceptions - (元素1,元素2) # 元素1賦值給request.user; 元素2賦值給request.auth - 區域性使用 from rest_framework.authentication import BaseAuthentication,BasicAuthentication class UserInfoView(APIView): """ 訂單相關業務 """ authentication_classes = [BasicAuthentication,] def get(self,request,*args,**kwargs): print(request.user) return HttpResponse('使用者資訊') - 全域性使用: REST_FRAMEWORK = { # 全域性使用的認證類 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ], # "UNAUTHENTICATED_USER":lambda :"匿名使用者" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None } 2. 原始碼流程 - dispatch - 封裝request - 獲取定義的認證類(全域性/區域性),通過列表生成時建立物件。 - initial - perform_authentication request.user(內部迴圈....) 2. 許可權 問題:不用檢視不用許可權可以訪問 基本使用: class MyPermission(object): def has_permission(self,request,view): if request.user.user_type != 3: return False return True class OrderView(APIView): """ 訂單相關業務(只有SVIP使用者有許可權) """ permission_classes = [MyPermission,] def get(self,request,*args,**kwargs): # request.user # request.auth self.dispatch ret = {'code':1000,'msg':None,'data':None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) 原始碼流程: - ... 梳理: 1. 使用 - 類,必須繼承:BasePermission,必須實現:has_permission方法 from rest_framework.permissions import BasePermission class SVIPPermission(BasePermission): message = "必須是SVIP才能訪問" def has_permission(self,request,view): if request.user.user_type != 3: return False return True - 返回值: - True, 有權訪問 - False,無權訪問 - 區域性 class UserInfoView(APIView): """ 訂單相關業務(普通使用者、VIP) """ permission_classes = [MyPermission1, ] def get(self,request,*args,**kwargs): return HttpResponse('使用者資訊') - 全域性 REST_FRAMEWORK = { "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission'] } 2. 原始碼流程 3. 訪問頻率控制(節流) 問題:控制訪問頻率 import time VISIT_RECORD = {} class VisitThrottle(object): """60s內只能訪問3次""" def __init__(self): self.history = None def allow_request(self,request,view): # 1. 獲取使用者IP remote_addr = request.META.get('REMOTE_ADDR') ctime = time.time() if remote_addr not in VISIT_RECORD: VISIT_RECORD[remote_addr] = [ctime,] return True history = VISIT_RECORD.get(remote_addr) self.history = history while history and history[-1] < ctime - 60: history.pop() if len(history) < 3: history.insert(0,ctime) return True # return True # 表示可以繼續訪問 # return False # 表示訪問頻率太高,被限制 def wait(self): """ 還需要等多少秒才能訪問 :return: """ ctime = time.time() return 60 - (ctime - self.history[-1]) class AuthView(APIView): """ 用於使用者登入認證 """ authentication_classes = [] permission_classes = [] throttle_classes = [VisitThrottle,] def post(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = "使用者名稱或密碼錯誤" # 為登入使用者建立token token = md5(user) # 存在就更新,不存在就建立 models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '請求異常' return JsonResponse(ret) 原始碼流程: ... 內建控制頻率類: from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "Luffy" def get_cache_key(self, request, view): return self.get_ident(request) class UserThrottle(SimpleRateThrottle): scope = "LuffyUser" def get_cache_key(self, request, view): return request.user.username REST_FRAMEWORK = { # 全域性使用的認證類 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ], # "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication', ], # "UNAUTHENTICATED_USER":lambda :"匿名使用者" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission'], "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"], "DEFAULT_THROTTLE_RATES":{ "Luffy":'3/m', "LuffyUser":'10/m', } } 梳理: a. 基本使用 - 類, 繼承:BaseThrottle,實現:allow_request、wait - 類, 繼承:SimpleRateThrottle,實現:get_cache_key、scope = "Luffy"(配置檔案中的key) b. 區域性 class AuthView(APIView): """ 用於使用者登入認證 """ authentication_classes = [] permission_classes = [] throttle_classes = [VisitThrottle,] # ******************* def post(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = "使用者名稱或密碼錯誤" # 為登入使用者建立token token = md5(user) # 存在就更新,不存在就建立 models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '請求異常' return JsonResponse(ret) c. 全域性 REST_FRAMEWORK = { # 全域性使用的認證類 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ], # "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication', ], # "UNAUTHENTICATED_USER":lambda :"匿名使用者" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission'], "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"], "DEFAULT_THROTTLE_RATES":{ "Luffy":'3/m', "LuffyUser":'10/m', } }