Django rest framework 简易使用方法
Django rest framework 工具包做API非常方便。
下面简单说一下几个功能的实现方法。
实现功能为,匿名用户访问首页一分钟能访问3次,登录用户一分钟访问6次,只有登录用户才能访问order页面。
第一步,注册app
1 INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 'app.apps.AppConfig', 9 'rest_framework', #注册 10 ]
settings文件注册app
第二步,定义URL,注意url路径最好使用名词。我们这里注册三个视图函数的url,实现验证,首页和定单页面。
1 from django.conf.urls import url 2 from django.contrib import admin 3 from app import views 4 5 urlpatterns = [ 6 url(r'^admin/', admin.site.urls), 7 url(r'^auth/', views.AuthView.as_view()), #验证 8 url(r'^index/', views.IndexView.as_view()), #首页 9 url(r'^order/', views.OrderView.as_view()), #定单 10 ]
url文件设置路由
第三步,auth视图函数
1 from rest_framework.views import APIView 2 from rest_framework.request import Request 3 from django.http import JsonResponse,HttpResponse 4 5 from app.utils.commons import gen_token 6 from app.utils.auth import LuffyAuthentication 7 from app.utils.throttle import LuffyAnonRateThrottle,LuffyUserRateThrottle 8 from app.utils.permission import LuffyPermission 9 from . import models 10 11 class AuthView(APIView): 12 13 """ 14 认证相关视图 15 由于继承了APIView,所以csrf就没有了,具体的源代码只是有一个装饰器, 16 加上了csrf_exempt装饰器,屏蔽了csrf 17 写法是在return的时候csrf_exempt(view) 和@使用装饰器效果是一样的,这种写法还可以写在url路由中。 18 """ 19 def post(self,request,*args,**kwargs): 20 """ 21 用户登录功能 22 :param request: 23 :param args: 24 :param kwargs: 25 :return: 26 """ 27 ret = {'code': 1000, 'msg': None} 28 # 默认要返回的信息 29 user = request.data.get('username') 30 # 这里的request已经不是原来的request了 31 pwd = request.data.get('password') 32 user_obj = models.UserInfo.objects.filter(user=user, pwd=pwd).first() 33 if user_obj: 34 tk = gen_token(user) #返回一个哈希过得字符串 35 #进行token验证 36 models.Token.objects.update_or_create(user=user_obj, defaults={'token': tk}) 37 # 数据库存入一个token信息 38 ret['code'] = 1001 39 ret['token'] = tk 40 else: 41 ret['msg'] = "用户名或密码错误" 42 return JsonResponse(ret)
上面的代码主要是实现了一个验证的功能,通过gen_token函数来验证,并存入数据库信息。
gen_token单独写到一个utils目录下的auth.py文件中。代码如下:
1 def gen_token(username): 2 import time 3 import hashlib 4 ctime = str(time.time()) 5 hash = hashlib.md5(username.encode('utf-8')) 6 hash.update(ctime.encode('utf-8')) 7 return hash.hexdigest()
通过时间和哈希等生成一个不重复的字符串。
第四步,index视图函数
1 class IndexView(APIView): 2 """ 3 用户认证 4 http://127.0.0.1:8001/v1/index/?tk=sdfasdfasdfasdfasdfasdf 5 获取用户传入的Token 6 7 首页限制:request.user 8 匿名:5/m 9 用户:10/m 10 """ 11 authentication_classes = [LuffyAuthentication,] 12 #认证成功返回一个用户名,一个对象,不成功就是None 13 throttle_classes = [LuffyAnonRateThrottle,LuffyUserRateThrottle] 14 #访问次数限制,如果合格都为True 15 def get(self,request,*args,**kwargs): 16 return HttpResponse('首页')
同样,将LuffyAuthentication,LuffyAnonRateThrottle,LuffyUserRateThrottle写到了utils目录下。代码如下:
auth.py :
1 from rest_framework.authentication import BaseAuthentication 2 from rest_framework import exceptions 3 from app import models 4 class LuffyAuthentication(BaseAuthentication): 5 def authenticate(self, request): 6 tk = request.query_params.get('tk') 7 if not tk: 8 return (None,None) 9 # raise exceptions.AuthenticationFailed('认证失败') 10 11 token_obj = models.Token.objects.filter(token=tk).first() 12 if not token_obj: 13 return (None,None) 14 15 return (token_obj.user,token_obj)
验证是否为登录用户,如果之前没有登陆过,则将token信息存到数据库
throttle.py :
1 from rest_framework.throttling import BaseThrottle,SimpleRateThrottle 2 3 4 class LuffyAnonRateThrottle(SimpleRateThrottle): 5 6 scope = "luffy_anon" 7 8 def allow_request(self, request, view): 9 """ 10 Return `True` if the request should be allowed, `False` otherwise. 11 """ 12 if request.user: 13 return True 14 15 # 获取当前访问用户的唯一标识 16 self.key = self.get_cache_key(request, view) 17 # 根据当前用户的唯一标识,获取所有访问记录 18 # [1511312683.7824545, 1511312682.7824545, 1511312681.7824545] 19 self.history = self.cache.get(self.key, []) 20 # 获取当前时间 21 self.now = self.timer() 22 23 # Drop any requests from the history which have now passed the 24 # throttle duration 25 while self.history and self.history[-1] <= self.now - self.duration: 26 self.history.pop() 27 if len(self.history) >= self.num_requests: #判断访问次数是否大于限制次数 28 return self.throttle_failure() 29 return self.throttle_success() #返回True 30 31 def get_cache_key(self, request, view): 32 return 'throttle_%(scope)s_%(ident)s' % { 33 'scope': self.scope, 34 'ident': self.get_ident(request), 35 36 # 判断是否为代理等等 37 38 } 39 40 class LuffyUserRateThrottle(SimpleRateThrottle): 41 scope = "luffy_user" 42 def allow_request(self, request, view): 43 """ 44 Return `True` if the request should be allowed, `False` otherwise. 45 """ 46 if not request.user: #判断登录直接返回True 47 return True 48 # 获取当前访问用户的唯一标识 49 # 用户对所有页面 50 # self.key = request.user.user 51 52 self.key = request.user.user + view.__class__.__name__ 53 # 用户对单页面的访问限制 54 55 # 根据当前用户的唯一标识,获取所有访问记录 56 # [1511312683.7824545, 1511312682.7824545, 1511312681.7824545] 57 self.history = self.cache.get(self.key, []) 58 # 获取当前时间 59 self.now = self.timer() 60 61 # Drop any requests from the history which have now passed the 62 # throttle duration 63 while self.history and self.history[-1] <= self.now - self.duration: 64 self.history.pop() 65 if len(self.history) >= self.num_requests: #访问次数的限制 66 return self.throttle_failure() 67 return self.throttle_success() #返回True
限制匿名用户和登录用户的访问次数,需要从settings中的配置拿去配置信息。
permission.py
1 from rest_framework.permissions import BasePermission 2 3 4 class LuffyPermission(BasePermission): 5 def has_permission(self, request, view): 6 """ 7 Return `True` if permission is granted, `False` otherwise. 8 """ 9 if request.user: 10 return True 11 return False
权限控制
第五步,order视图函数
1 class OrderView(APIView): 2 """ 3 订单页面:只有登录成功后才能访问 4 - 认证(匿名和用户) 5 - 权限(用户) 6 - 限制() 7 """ 8 authentication_classes = [LuffyAuthentication, ] 9 permission_classes = [LuffyPermission,] #登录就返回True 10 throttle_classes = [LuffyAnonRateThrottle, LuffyUserRateThrottle] 11 12 def get(self,request,*args,**kwargs): 13 14 return HttpResponse('订单')
第六步,settings配置
1 REST_FRAMEWORK = { 2 'UNAUTHENTICATED_USER': None, 3 'UNAUTHENTICATED_TOKEN': None, 4 "DEFAULT_THROTTLE_RATES": { 5 'luffy_anon': '3/m', #匿名用户一分钟访问3次 6 'luffy_user': '6/m' #登录用户一分钟访问6次 7 }, 8 }
最后,实现功能为,匿名用户访问首页一分钟能访问3次,登录用户一分钟访问6次,只有登录用户才能访问order页面。
学习Django rest framework需要随时查看源代码,判断源代码的逻辑思路来自定义自己的功能,如此学习效率极高。
中天一片无情月,是我平生不悔心