![](http://static.javashuo.com/static/loading.gif)
REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默認版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 容許的版本 'VERSION_PARAM': 'version' # URL中獲取值的key }
![](http://static.javashuo.com/static/loading.gif)
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view(), name='test'), ]
![](http://static.javashuo.com/static/loading.gif)
#!/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請求,響應內容')
d. 基於主機名方法
如:v1.example.com
![](http://static.javashuo.com/static/loading.gif)
ALLOWED_HOSTS = ['*'] REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默認版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 容許的版本 'VERSION_PARAM': 'version' # URL中獲取值的key }
![](http://static.javashuo.com/static/loading.gif)
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view(), name='test'), ]
![](http://static.javashuo.com/static/loading.gif)
#!/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請求,響應內容')
e. 基於django路由系統的namespace
如:example.com/v1/users/
![](http://static.javashuo.com/static/loading.gif)
REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默認版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 容許的版本 'VERSION_PARAM': 'version' # URL中獲取值的key }
![](http://static.javashuo.com/static/loading.gif)
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')), ]
![](http://static.javashuo.com/static/loading.gif)
#!/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請求,響應內容')
f. 全局使用
![](http://static.javashuo.com/static/loading.gif)
REST_FRAMEWORK = { 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_VERSION': 'v1', 'ALLOWED_VERSIONS': ['v1', 'v2'], 'VERSION_PARAM': 'version' }
DRF的versioning模塊
![](http://static.javashuo.com/static/loading.gif)
# 基礎類 class BaseVersioning(object): default_version = api_settings.DEFAULT_VERSION allowed_versions = api_settings.ALLOWED_VERSIONS version_param = api_settings.VERSION_PARAM def determine_version(self, request, *args, **kwargs): msg = '{cls}.determine_version() must be implemented.' raise NotImplementedError(msg.format( cls=self.__class__.__name__ )) def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra): return _reverse(viewname, args, kwargs, request, format, **extra) def is_allowed_version(self, version): if not self.allowed_versions: return True return ((version is not None and version == self.default_version) or (version in self.allowed_versions)) # 在請求頭中攜帶版本信息 class AcceptHeaderVersioning(BaseVersioning): """ GET /something/ HTTP/1.1 Host: example.com Accept: application/json; version=1.0 """ # 在URL中攜帶版本信息 class URLPathVersioning(BaseVersioning): ''' urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'), url(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail') ] ''' # 在namespace中攜帶版本信息 class NamespaceVersioning(BaseVersioning): ''' # users/urls.py urlpatterns = [ url(r'^/users/$', users_list, name='users-list'), url(r'^/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail') ] # urls.py urlpatterns = [ url(r'^v1/', include('users.urls', namespace='v1')), url(r'^v2/', include('users.urls', namespace='v2')) ] ''' # 在域名中攜帶版本信息 class HostNameVersioning(BaseVersioning): """ GET /something/ HTTP/1.1 Host: v1.example.com Accept: application/json """ # 在參數中攜帶版本信息 class QueryParameterVersioning(BaseVersioning): """ GET /something/?version=0.1 HTTP/1.1 Host: example.com Accept: application/json """
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認證
![](http://static.javashuo.com/static/loading.gif)
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)
執行:makemigrations AuthDemo
migrate AuthDemo
![](http://static.javashuo.com/static/loading.gif)
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")), ]
![](http://static.javashuo.com/static/loading.gif)
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()), ]
![](http://static.javashuo.com/static/loading.gif)
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("權限測試接口")
![](http://static.javashuo.com/static/loading.gif)
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", ] }
![](http://static.javashuo.com/static/loading.gif)
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 False
![](http://static.javashuo.com/static/loading.gif)
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)