DRF的版本、認證、權限
DRF的版本
版本控制是做什麽用的, 我們為什麽要用
首先我們要知道我們的版本是幹嘛用的呢~~大家都知道我們開發項目是有多個版本的~~
當我們項目越來越更新~版本就越來越多~~我們不可能新的版本出了~以前舊的版本就不進行維護了~~~
那我們就需要對版本進行控制~~這個DRF也給我們提供了一些封裝好的版本控制方法~~
版本控制怎麽用
之前我們學視圖的時候知道APIView,也知道APIView返回View中的view函數,然後調用的dispatch方法~
執行self.initial方法之前是各種賦值,包括request的重新封裝賦值,下面是路由的分發,那我們看下這個方法都做了什麽~~
我們可以看到,我們的version版本信息賦值給了 request.version 版本控制方案賦值給了 request.versioning_scheme~~
其實這個版本控制方案~就是我們配置的版本控制的類~~
也就是說,APIView通過這個方法初始化自己提供的組件~~
我們接下來看看框架提供了哪些版本的控制方法~~在rest_framework.versioning裏~~
詳細用法
a. 基於url的get傳參方式
如:/users?version=v1
REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, #settings.py默認版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允許的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中獲取值的key }
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view(),name=‘test‘), ]urls.py
#!/usr/bin/env pythonviews.py# -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import QueryParameterVersioning class TestView(APIView): versioning_class = QueryParameterVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET請求,響應內容‘) def post(self, request, *args, **kwargs): return Response(‘POST請求,響應內容‘) def put(self, request, *args, **kwargs): return Response(‘PUT請求,響應內容‘) views.py
b. 基於url的正則方式
如:/v1/users/
REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默認版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允許的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中獲取值的key }settings.py
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^(?P<version>[v1|v2]+)/test/‘, TestView.as_view(), name=‘test‘), ] urls.pyurls.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import URLPathVersioning class TestView(APIView): versioning_class = URLPathVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET請求,響應內容‘) def post(self, request, *args, **kwargs): return Response(‘POST請求,響應內容‘) def put(self, request, *args, **kwargs): return Response(‘PUT請求,響應內容‘) views.pyviews.py
c. 基於 accept 請求頭方式
如:Accept: application/json; version=1.0
REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默認版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允許的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中獲取值的key }settings.py
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view(), name=‘test‘), ]urls.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import AcceptHeaderVersioning class TestView(APIView): versioning_class = AcceptHeaderVersioning def get(self, request, *args, **kwargs): # 獲取版本 HTTP_ACCEPT頭 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET請求,響應內容‘) def post(self, request, *args, **kwargs): return Response(‘POST請求,響應內容‘) def put(self, request, *args, **kwargs): return Response(‘PUT請求,響應內容‘)views.py
d. 基於主機名方法
如:v1.example.com
ALLOWED_HOSTS = [‘*‘] REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默認版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允許的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中獲取值的key }settings.py
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view(), name=‘test‘), ]urls.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import HostNameVersioning class TestView(APIView): versioning_class = HostNameVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET請求,響應內容‘) def post(self, request, *args, **kwargs): return Response(‘POST請求,響應內容‘) def put(self, request, *args, **kwargs): return Response(‘PUT請求,響應內容‘)views.py
e. 基於django路由系統的namespace
如:example.com/v1/users/
REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默認版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允許的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中獲取值的key }settings.py
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^v1/‘, ([ url(r‘test/‘, TestView.as_view(), name=‘test‘), ], None, ‘v1‘)), url(r‘^v2/‘, ([ url(r‘test/‘, TestView.as_view(), name=‘test‘), ], None, ‘v2‘)), ]urls.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import NamespaceVersioning class TestView(APIView): versioning_class = NamespaceVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET請求,響應內容‘) def post(self, request, *args, **kwargs): return Response(‘POST請求,響應內容‘) def put(self, request, *args, **kwargs): return Response(‘PUT請求,響應內容‘)views.py
f. 全局使用
REST_FRAMEWORK = { ‘DEFAULT_VERSIONING_CLASS‘:"rest_framework.versioning.URLPathVersioning", ‘DEFAULT_VERSION‘: ‘v1‘, ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], ‘VERSION_PARAM‘: ‘version‘ }settings.py
DRF的認證
上面講版本的時候我們知道~在dispatch方法裏~執行了initial方法~~那裏初始化了我們的版本~~
如果我們細心我們能看到~版本的下面其實就是我們的認證,權限,頻率組件了~~
我們先看看我們的認證組件~~
我們進去我們的認證看下~~
我們這個權限組件返回的是request.user,那我們這裏的request是新的還是舊的呢~~
我們的initial是在我們request重新賦值之後的~所以這裏的request是新的~也就是Request類實例對象~~
那這個user一定是一個靜態方法~我們進去看看~~
很明顯,有傳參
我們通過上面基本可以知道我們的認證類一定要實現的方法~~以及返回值類型~~以及配置的參數authentication_classes~
DRF的權限
權限是什麽
大家之前都應該聽過權限~那麽我們權限到底是做什麽用的呢~~
大家都有博客~或者去一些論壇~一定知道管理員這個角色~
比如我們申請博客的時候~一定要向管理員申請~也就是說管理員會有一些特殊的權利~是我們沒有的~~
這些對某件事情決策的範圍和程度~我們叫做權限~~權限是我們在項目開發中非常常用到的~~
那我們看DRF框架給我們提供的權限組件都有哪些方法~~
權限組件源碼
我們之前說過了DRF的版本和認證~也知道了權限和頻率跟版本認證都是在initial方法裏初始化的~~
其實我們版本,認證,權限,頻率控制走的源碼流程大致相同~~大家也可以在源碼裏看到~~
我們的權限類一定要有has_permission方法~否則就會拋出異常~~這也是框架給我提供的鉤子~~
我們先看到在rest_framework.permissions這個文件中~存放了框架給我們提供的所有權限的方法~~
我這裏就不帶著大家詳細去看每一個了~大家可以去瀏覽一下每個權限類~看看每個都是幹嘛的~~
這裏主要說下BasePermission 這個是我們寫權限類繼承的一個基礎權限類~~~
認證權限的詳細用法
用戶url傳入的token認證
from django.db import models # Create your models here. class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) token = models.UUIDField(null=True, blank=True)#隨機字符串 CHOICES = ((1, "vip"), (2, "普通用戶"), (3, "vvip")) type = models.IntegerField(choices=CHOICES, default=2)DRFDemo/AuthDemo/models.py
執行:makemigrations AuthDemo
migrate AuthDemo
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^book/‘, include("SerDemo.urls")), url(r‘^api/user/‘, include("AuthDemo.urls")), url(r‘^api/(?P<version>[v1|v2]+)/‘, include("VersionDemo.urls")), ]DRFDemo/DRFDemo/urls.py
from django.conf.urls import url, include from django.contrib import admin from .views import RegisterView, LoginView, TestView, PermissionView urlpatterns = [ url(r‘^register‘, RegisterView.as_view()), url(r‘^login‘, LoginView.as_view()), url(r‘^test‘, TestView.as_view()), url(r‘^permission‘, PermissionView.as_view()), ]DRFDemo/AuthDemo/urls.py
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.response import Response from .models import User import uuid from utils.auth import MyAuth from utils.permission import MyPermission # Create your views here. class RegisterView(APIView): def post(self, request): name = request.data.get("name", "") pwd = request.data.get("pwd", "") if name and pwd: User.objects.create(name=name, pwd=pwd) return Response("註冊成功") return Response("用戶名或密碼不合法") class LoginView(APIView): def post(self, request): name = request.data.get("name", "") pwd = request.data.get("pwd", "") user_obj = User.objects.filter(name=name, pwd=pwd).first() if user_obj: # 登錄成功 創建一個token並給前端返回 token = uuid.uuid4() user_obj.token = token user_obj.save() return Response(token) return Response("用戶名或密碼錯誤") class TestView(APIView): authentication_classes = [MyAuth, ] def get(self, request): print(request.user) print(request.user.name) print(request.auth) return Response("登錄後發送的數據") class PermissionView(APIView): authentication_classes = [MyAuth, ] permission_classes = [MyPermission, ] def get(self, request): # 這個接口只能vip或者vvip訪問 return Response("權限測試接口")DRFDemo/AuthDemo/views.py
REST_FRAMEWORK = { # "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion", "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", ‘DEFAULT_VERSION‘: "v1", ‘ALLOWED_VERSIONS‘: ["v1", "v2"], ‘VERSION_PARAM‘: ‘version‘, # 配置認證類 # "DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth", ] }DRFDemo/DRFDemo/settings.py
from rest_framework import permissions class MyPermission(permissions.BasePermission): message = "請充VIP,999一年" def has_permission(self, request, view): # 判斷用戶是否有權限 if request.user.type in [1, 3]: return True return FalseDRFDemo/utils/permission.py
DRF的版本、認證、權限