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