
REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默认版本 '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'), ]

#!/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

ALLOWED_HOSTS = ['*'] REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默认版本 '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'), ]

#!/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/

REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默认版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 容许的版本 'VERSION_PARAM': 'version' # URL中获取值的key }

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')), ]

#!/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. 全局使用

REST_FRAMEWORK = { 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_VERSION': 'v1', 'ALLOWED_VERSIONS': ['v1', 'v2'], 'VERSION_PARAM': 'version' }
DRF的versioning模块

# 基础类 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认证

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

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")), ]

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()), ]

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("权限测试接口")

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", ] }

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

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)