1.版本控制
1.1版本控制是做什么用的, 我们为什么要用
首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~
随着我们项目的更新~版本就越来越多~~我们不可能新的版本出了~以前旧的版本就不进行维护了~~~
那我们就需要对版本进行控制~~这个DRF也给我们提供了一些封装好的版本控制方法~~
1.2版本控制怎么用
之前我们学视图的时候知道APIView,也知道APIView返回View中的view函数,然后调用的dispatch方法~
那我们现在看下APIView.dispatch方法~~看下它都做了什么~~
执行self.initial方法之前是各种赋值,包括request的重新封装赋值,下面是路由的分发,那我们看下initial这个方法都做了什么~~
我们可以看到,我们的version版本信息赋值给了 request.version 版本控制方案赋值给了 request.versioning_scheme~~
其实这个版本控制方案~就是我们配置的版本控制的类~~
也就是说,APIView通过这个方法初始化自己提供的组件~~
我们接下来看看框架提供了哪些版本的控制方法~~在rest_framework.versioning里~~
1.3版本控制的使用
我滴个神,试了其他的试了一个多小时,怎么弄都不行,我也是没招了!!稍后处理!!
错在了一个小点,我滴神,django2.0中是re_path=url,我用了path....
没看到那个警告信息。。55555555555555555555555555
1.3.1QueryParameterVersioning
settings.py
REST_FRAMEWORK = {
# 默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.QueryParameterVersioning',
# 允许的版本
'ALLOWED_VERSIONS': ['v1', 'v2'],
# 版本使用的参数名称
'VERSION_PARAM': 'version',
# 默认使用的版本
'DEFAULT_VERSION': 'v1',
}
views.py
class DemoView(APIView):
def get(self, request):
print("request.version", request.version)
print("request.versioning_scheme", request.versioning_scheme)
# 得到版本号 根据版本号的不同返回不同的信息
if request.version == "v1":
return Response("v1版本的数据")
elif request.version == "v2":
return Response("v2版本的数据")
return Response("不存在的版本")
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path(r"demo", DemoView.as_view()),
]
1.3.2URLPathVersioning
settings.py
REST_FRAMEWORK = {
# 默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
# 允许的版本
'ALLOWED_VERSIONS': ['v1', 'v2'],
# 版本使用的参数名称
'VERSION_PARAM': 'version',
# 默认使用的版本
'DEFAULT_VERSION': 'v1',
}
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'api/(?P<version>(v1|v2))/demo/', DemoView.as_view(), name='demo'),
]
views.py
class DemoView(APIView):
def get(self, request, *args, **kwargs):
print("request.version", request.version)
print("request.versioning_scheme", request.versioning_scheme)
# 得到版本号 根据版本号的不同返回不同的信息
if request.version == "v1":
return Response("v1版本的数据")
elif request.version == "v2":
return Response("v2版本的数据")
return Response("不存在的版本")
其他的参考源代码就可以了,一定注意这个re_path,带有正则匹配时,使用的是re_path!!!
1.3.3自定义版本类
utils.py
# by gaoxin
from rest_framework import versioning
class MyVersion(object):
def determine_version(self, request, *args, **kwargs):
# 返回值 给了request.version
# 返回版本号
# 版本号携带在过滤条件 xxxx?version=v1
version = request.query_params.get("version", "v1")
return version
settings.py
REST_FRAMEWORK = {
# 默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion',
}
views.py
class DemoView(APIView):
def get(self, request, *args, **kwargs):
print("request.version", request.version)
print("request.versioning_scheme", request.versioning_scheme)
# 得到版本号 根据版本号的不同返回不同的信息
if request.version == "v1":
return Response("v1版本的数据")
elif request.version == "v2":
return Response("v2版本的数据")
return Response("不存在的版本")
2.认证
2.1认证作用
我们都知道~我们可以在网站上登录~然后可以有个人中心,对自己信息就行修改~~~
但是我们每次给服务器发请求,由于Http的无状态,导致我们每次都是新的请求~~
那么服务端需要对每次来的请求进行认证,看用户是否登录,以及登录用户是谁~~
那么我们服务器对每个请求进行认证的时候,不可能在每个视图函数中都写认证~~~
一定是把认证逻辑抽离出来~~以前我们可能会加装饰器~或者中间件~~那我们看看DRF框架给我们提供了什么~~~
2.2认证流程
我们这个权限组件返回的是request.user,那我们这里的request是新的还是旧的呢~~
我们的initial是在我们request重新赋值之后的~所以这里的request是新的~也就是Request类实例对象~~
那这个user一定是一个静态方法~我们进去看看~~
2.3认证试验
models.py
class User(models.Model):
username = models.CharField(max_length=32)
pwd = models.CharField(max_length=16)
token = models.UUIDField()
views.py
from django.shortcuts import render
import uuid
from app.models import User
from utils.auth import MyAuth
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
class DemoView(APIView):
def get(self, request):
return Response("认证demo~")
class LoginView(APIView):
def post(self, request):
username = request.data.get("username")
pwd = request.data.get("pwd")
# 登录成功 生成token 会把token给你返回
token = uuid.uuid4()
User.objects.create(username=username, pwd=pwd, token=token)
return Response("创建用户成功")
class TestView(APIView):
#配置局部认证
authentication_classes = [MyAuth,]
def get(self, request):
print(request.user) # User object (1)
print(request.auth) # a890ec1e18c146f2b8542eb465bd6774
user_id = request.user.id
return Response("认证测试")
urls.py
from django.contrib import admin
from django.urls import path,include,re_path
from app.views import DemoView,LoginView, TestView
from rest_framework.routers import DefaultRouter
import rest_framework.versioning
router = DefaultRouter()
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'api/demo/', DemoView.as_view(), name='demo'),
re_path(r"login", LoginView.as_view()),
re_path(r"test", TestView.as_view()),
]
utils/auth.py
# by gaoxin
from rest_framework.exceptions import AuthenticationFailed
from app.models import User
from rest_framework.authentication import BaseAuthentication
class MyAuth(BaseAuthentication):
def authenticate(self, request):
# 做认证 看他是否登录
# 从url过滤条件里拿到token
# 去数据库看token是否合法
# 合法的token能够获取用户信息
token = request.query_params.get("token", "")
if not token:
raise AuthenticationFailed("没有携带token")
user_obj = User.objects.filter(token=token).first()
if not user_obj:
raise AuthenticationFailed("token不合法")
# return (None, None)
return (user_obj, token)
2.4配置全局认证
配置在settings.py中
REST_FRAMEWORK = {
# 默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion',
"DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth", ]
}