国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Django Rest framework之權限的實現示例

2020-01-04 13:48:28
字體:
來源:轉載
供稿:網友

一、權限實例

在閱讀本文之前請先參考django rest framework 之 認證 中關于 django rest framework 的相關內容及實例

1、目錄結構

為了更好的管理各個功能組件,在django rest framework 之 認證 中我們說到可以將認證類單獨的拿出來,放到其他目錄下,然后導入到 views.py 文件中,在權限環節我們亦可以這么做,目錄結構就變成這樣

Django,Rest,framework,權限

在api這個app下創建一個utils包專門用來存放相關的組件。

2、為模型類添加認證字段

我們在models.py中定義了兩個模型類,分別是

from django.db import modelsclass UserInfo(models.Model):  USER_TYPE = (    (1,'普通用戶'),    (2,'VIP'),    (3,'SVIP')  )  user_type = models.IntegerField(choices=USER_TYPE, default=1)  username = models.CharField(max_length=32)  password = models.CharField(max_length=64)class UserToken(models.Model):  user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)  token = models.CharField(max_length=64)

在 UserInfo 中通過為用戶添加一個 user_type 字段來保證用戶的身份,是普通用戶,VIP還是SVIP,這樣就可以通過用戶的身份驗證不同的權限。如果想要定義一個視圖類,這個類中的邏輯只有超級用戶才能訪問。

3、具體權限認證

可以再utils中的 permissions.py 中這么寫

# utils/permission.pyclass SVIPPremission(object):  message = "必須是SVIP才能訪問" # 這里的message表示如果不通過權限的時候,錯誤提示信息  def has_permission(self,request,view):    if request.user.user_type != 3:      return False    return Trueclass MyPremission(object):  # 這個權限類表示當用戶為SVIP時不可通過  def has_permission(self,request,view):    if request.user.user_type == 3:      return False    return True

這里只是判斷用戶的 USER_TYPE 的字段,判斷用戶是否有權限,也可以添加其他的邏輯進行判斷。

4、全局配置

在上一節的django rest framework 之 認證 的認證中,將認證類放到了 settings.py 文件中,這樣會作用到視圖中的每一個視圖類,如果視圖類想要自己進行認證,只需要重寫 authentication_classes 即可,那么對于權限來說我們也可以這么做,

REST_FRAMEWORK = {  'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],   "UNAUTHENTICATED_USER": None, # 匿名,request.user = None  "UNAUTHENTICATED_TOKEN": None,# 匿名,request.auth = None  "DEFAULT_PERMISSION_CLASSES": ['api.utils.permission.MyPermission'], # 表示每一個視圖類(只要不重寫permission_classes屬性),都需要SVIP的用戶才能訪問。}

5、視圖

在視圖 view.py 中定義一個用戶詳情類 UserInfoView 作為測試,這里的視圖和上一節的django rest framework 之 認證 是相接的。

from django.shortcuts import render, HttpResponsefrom django.http import JsonResponsefrom django.views import Viewfrom rest_framework.views import APIViewfrom rest_framework.request import Requestfrom .utils import authenticate, permissionfrom api import modelsimport jsondef md5(user):  import hashlib  import time  # 當前時間,相當于生成一個隨機的字符串  ctime = str(time.time())  # token加密  m = hashlib.md5(bytes(user, encoding='utf-8'))  m.update(bytes(ctime, encoding='utf-8'))  return m.hexdigest()class AuthView(APIView):  '''用于用戶登錄驗證'''  authentication_classes = []   #里面為空,代表不需要認證  permission_classes = []     #不里面為空,代表不需要權限  def get(self, request, *args, **kwargs):    ret = {'code': 1000, 'msg': 'success', 'name': '偷偷'}    ret = json.dumps(ret, ensure_ascii=False)    return HttpResponse(ret)  def post(self,request,*args,**kwargs):    ret = {'code':1000,'msg':None}    try:      user = request.POST.get('username')      pwd = request.POST.get('password')      print(user, pwd)      obj = models.UserInfo.objects.filter(username=user,password=pwd).first()      print(obj.username, obj.password)      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)ORDER_DICT = {  1:{    'name':'apple',    'price':15  },  2:{    'name':'狗子',    'price':100  }}class OrderView(APIView):  # 用戶想要獲取訂單,就要先通過身份認證、在全局settings.py 中已經配置  permission_classes = []  def get(self, request, *args, **kwargs):    ret = {      'code': 1024,      'msg': '訂單獲取成功',    }    try:      ret['data'] = ORDER_DICT    except Exception as e:      pass    return JsonResponse(ret)  class UserInfoView(APIView):  permission_classes = [permission.SVIPPermission]  def get(self, request, *args, **kwargs):    print(request.user)    return HttpResponse('SVIP用戶信息')

這里的 UserInfoView 重寫了 permission_classes 屬性,則不會再使用 settings.py 中關于認證類的配置。表示只有SVIP才能訪問這個類的內部。

6、路由分發

在url.py中設置路由分發

from django.conf.urls import urlfrom api.views import AuthView, OrderView, UserInfoViewurlpatterns = [  url(r'^api/v1/auth/$', AuthView.as_view()),  url(r'^api/v1/order/$', OrderView.as_view()),  url(r'^api/v1/info/$', UserInfoView.as_view()),]

7、請求測試

Postman或者瀏覽器發送請求,由于我們在 setting.py 中配置了 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],

會對請求進行認證,所以要帶這用戶的 token 才能通過,進入到權限組件。

進入sqlite數據庫,找到對應的注冊用戶

Django,Rest,framework,權限

在數據庫中,拿到刷新的用戶的最近一次的token

Django,Rest,framework,權限

拿到這個token發送請求

Django,Rest,framework,權限

請求成功,則說明權限生效,也可以在將 UserInfoView 改成如下

class UserInfoView(APIView):  permission_classes = [permission.SVIPPermission]  def get(self, request, *args, **kwargs):    print(request.user)    return HttpResponse('SVIP用戶信息')

在發送請求,就會發現用戶不會有權限的提示信息。如下

Django,Rest,framework,權限

二、源碼分析

像 django rest framework 之 認證 一樣進入, request 的請求流程,進入源碼查看具體權限的操作

1、進入dispath()方法

Django,Rest,framework,權限

2、進入initial()方法

Django,Rest,framework,權限

3、進入check_permissions()方法

Django,Rest,framework,權限

4、權限類的具體操作

在這里可以看到和認證中有類似的操作,獲取所有的權限類,并且執行每一個權限類的 has_permission() 方法,而這個方法具體封裝了我們的判斷權限操作,但是 has_permission() 方法的返回值需要時 False 或者 True , self.permission_denied(request, message=getattr(permission, 'message', None)) 說明可以在權限類中重寫 message 屬性,來定義權限不通過時候的提示信息。

Django,Rest,framework,權限

進入 self.get_permissions() 來看一下

4、獲取所有的權限類

Django,Rest,framework,權限

Django,Rest,framework,權限

在APIView中有定義默認的權限類,因此也可以通過全局配置的方法配置權限類。

5、原生的權限類

像認證那樣, django rest framework 中也有權限類

Django,Rest,framework,權限

可以根據自己的需要調用。

三、總結

權限其實的流程跟之前的認證流程是一樣的,認證類封裝到 request 中,然后再調用認證類的方法,不過這里的方法返回值不再是像認證組件那樣的直接返回一個認證的對象,而是返回一個 True 或者 False 值表示認證過的對象是否有某些權限再進行具體操作。

這里注意的是,在自己重寫權限類的相關方法,添加自己的邏輯的時候,返回值需要是一個布爾值, Flase 或者 True ,表示是否有權限。也可以通過全局配置和局部配置權限類。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到python教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 噶尔县| 固安县| 白山市| 淮安市| 二连浩特市| 浮梁县| 西华县| 大连市| 布尔津县| 磐石市| 山阳县| 壤塘县| 临夏市| 韶山市| 舟山市| 徐闻县| 苗栗市| 崇仁县| 紫阳县| 双辽市| 洪雅县| 友谊县| 商城县| 浪卡子县| 保亭| 北流市| 景德镇市| 达日县| 金昌市| 逊克县| 富锦市| 建平县| 武宣县| 布尔津县| 台南市| 南川市| 平原县| 定南县| 定西市| 上栗县| 松滋市|