新建一個項目,採用路由分發的方式,採用以前的數據庫表的例子並添加修改python
目錄結構以下:sql
demo\ api\ migrations\ __init__.py __init__.py admin.py apps.py models.py tests.py urls.py # 路由分發後的urls views.py demo\ __init__.py settings.py urls.py wsgi.py templates db.sqlite3 manage.py
# demo\api\models.py from django.db import models class UserGroup(models.Model): title = models.CharField(max_length=32) class UerInfo(models.Model): user_type_choices = ( (1, '普通用戶'), (2, 'VIP'), (3, 'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32, unique=True) password = models.CharField(max_length=64) roles = models.ManyToManyField("Role") group = models.ForeignKey("UserGroup") class UserToken(models.Model): user = models.OneToOneField(to='UerInfo') token = models.CharField(max_length=64) class Role(models.Model): title = models.CharField(max_length=32)
# demo\demo\urls.py from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^api/', admin.site.urls), url(r'^api/', include('api.urls')), ]
# demo\api\urls.py from django.conf.urls import url from api import views urlpatterns = [ url(r'^users/$', views.UsersView.as_view()), ]
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView class UsersView(APIView): def get(self, request, *args, **kwargs): # 經過原生的request version = request._request.GET.get('version') print(version) return HttpResponse("用戶列表")
啓動項目,在瀏覽器輸入 http://127.0.0.1:8000/api/users/?version=v1
,後臺會返回一個 v1
,這是經過訪問原生的 request
去獲取版本數據庫
還有一種方法,經過 query_params
訪問django
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView class UsersView(APIView): def get(self, request, *args, **kwargs): version = request.query_params.get('version') print(version) return HttpResponse("用戶列表")
由於這是 query_params
內部本身訪問原生的 request
,達到一樣的效果json
經過上面的 query_params
,能夠自定義一個版本的組件,從而獲取版本api
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView class ParamVersion(object): def determine_version(self, request, *args, **kwargs): version = request.query_params.get('version') return version class UsersView(APIView): versioning_class = ParamVersion def get(self, request, *args, **kwargs): print(request.version) return HttpResponse("用戶列表")
啓動項目,在瀏覽器輸入 http://127.0.0.1:8000/api/users/?version=v2
,後臺會返回一個 v2
瀏覽器
還能夠使用內置的方法去獲取版本app
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView from rest_framework.versioning import QueryParameterVersioning class UsersView(APIView): versioning_class = QueryParameterVersioning def get(self, request, *args, **kwargs): print(request.version) return HttpResponse("用戶列表")
# 進入 QueryParameterVersioning 查看 class QueryParameterVersioning(BaseVersioning): """ GET /something/?version=0.1 HTTP/1.1 Host: example.com Accept: application/json """ invalid_version_message = _('Invalid version in query parameter.') def determine_version(self, request, *args, **kwargs): # 這裏的與上面本身所寫的幾乎相同,而且它還有默認的版本(能夠在配置文件中設置) version = request.query_params.get(self.version_param, self.default_version) # is_allowed_version是容許的版本 if not self.is_allowed_version(version): raise exceptions.NotFound(self.invalid_version_message) return version # 反向生成URL def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra): url = super(QueryParameterVersioning, self).reverse( viewname, args, kwargs, request, format, **extra ) if request.version is not None: return replace_query_param(url, self.version_param, request.version) return url
能夠在配置文件中設置默認的版本函數
# demo\demo\settings.py # 在末尾添加 REST_FRAMEWORK = { "DEFAULT_VERSION": 'v1', # 默認版本 "ALLOWED_VERSION": ['v1', 'v2'], # 容許使用的版本 "VERSION_PARAM": 'version' # url中的key值 }
如今在瀏覽器中,只能經過訪問 http://127.0.0.1:8000/api/users/
或 http://127.0.0.1:8000/api/users/?version=v1
或 http://127.0.0.1:8000/api/users/?version=v2
的方式從後臺獲取數據url
它也是個內置的方法
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView from rest_framework.versioning import URLPathVersioning class UsersView(APIView): versioning_class = URLPathVersioning def get(self, request, *args, **kwargs): print(request.version) return HttpResponse("用戶列表")
由於是經過路徑傳參,因此在 url 中須要有所改動
# demo\api\urls.py from django.conf.urls import url from api import views urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view()), ]
這時在瀏覽器中經過 http://127.0.0.1:8000/api/v1/users/
也能夠在後臺獲取 v1
,這時推薦的使用方式
能夠設置在配置文件中,作全局的設置,在視圖函數中即可以省略
# demo\demo\settings.py REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION": 'v1', "ALLOWED_VERSION": ['v1', 'v2'], "VERSION_PARAM": 'version' }
# demo\api\views.py from django.shortcuts import render, HttpResponse from rest_framework.views import APIView class UsersView(APIView): def get(self, request, *args, **kwargs): print(request.version) return HttpResponse("用戶列表")
請求進來,先走 dispatch
,對 request
進行封裝,走 initial
def initial(self, request, *args, **kwargs): ... # 省略的內容 # Determine the API version, if versioning is in use. version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted # 認證、權限、頻率 self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request)
def determine_version(self, request, *args, **kwargs): """ If versioning is being used, then determine any API version for the incoming request. Returns a two-tuple of (version, versioning_scheme) """ if self.versioning_class is None: return (None, None) # 處理版本類的對象,就是 settings.py中 URLPathVersioning類的對象 scheme = self.versioning_class() # 返回兩個值,第一個是調用determine_version的方法,根據請求獲取版本 # 第二個scheme是處理版本的對象 return (scheme.determine_version(request, *args, **kwargs), scheme)
class APIView(View): ... # 省略的內容 versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
先處理版本再走認證、權限、頻率
from django.shortcuts import render, HttpResponse from rest_framework.views import APIView from django.urls import reverse class UsersView(APIView): def get(self, request, *args, **kwargs): # 1. 獲取版本 print(request.version) # 2. 獲取版本處理的對象 print(request.versioning_scheme) # 反向自動生成URL(你在瀏覽器訪問的url會給你打印出來) u1 = request.versioning_scheme.reverse(viewname='uu', request=request) print(u1) # 手動生成 u2 = reverse(viewname='uu', kwargs={'version':2}) print(u2) return HttpResponse("用戶列表")
配置文件
REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":'v1', "ALLOWED_VERSIONS":['v1','v2'], "VERSION_PARAM":'version', }
路由系統
urlpatterns = [ url(r'^api/', admin.site.urls), url(r'^api/', include('api.urls')), ] urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(), name='uu'), ]
視圖