新建一個工程Myproject和一個名爲api的app(這裏使用的Django版本是1.11)正則表達式
分別寫下如下代碼數據庫
一、api/models.pydjango
from django.db import models class UserInfo(models.Model): USER_TYPE = ( (1,'普通用戶'), (2,'VIP'), (3,'SVIP') ) user_type = models.IntegerField(choices=USER_TYPE) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) group = models.ForeignKey('UserGroup',on_delete=models.CASCADE) roles = models.ManyToManyField('Role') class UserToken(models.Model): user = models.OneToOneField('UserInfo',on_delete=models.CASCADE) token = models.CharField(max_length=64) class UserGroup(models.Model): title = models.CharField(max_length=32) class Role(models.Model): title = models.CharField(max_length=32)
二、Myproject/urls.pyjson
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url('admin/', admin.site.urls), url('api/', include('api.urls')), ]
三、api/urls.pyapi
from django.conf.urls import url, include from .views import UserView urlpatterns = [ url('users/', UserView.as_view()), ]
四、api/views.py瀏覽器
# api/views.py from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.request import Request from rest_framework.versioning import QueryParameterVersioning class UserView(APIView): versioning_class = QueryParameterVersioning def get(self,request,*args,**kwargs): #獲取版本 print(request.version) return HttpResponse('用戶列表')
五、settings.pysession
#版本 REST_FRAMEWORK = { "DEFAULT_VERSION":'v1', #默認的版本 "ALLOWED_VERSIONS":['v1','v2'], #容許的版本 "VERSION_PARAM":'version' #GET方式url中參數的名字 ?version=xxx }
同時咱們是經過網頁測試的,因此在settings中應該註冊'rest_framework'app
settings.py中找到對應的位置添加下面黃色部位ide
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api.apps.ApiConfig', 'rest_framework' ]
上面就是這些代碼下面是咱們測試的結果,post
一、url中經過GET傳參
啓動項目在網頁中訪問該網址:http://127.0.0.1:8000/api/users/?version=v2
網頁顯示用戶列表,在Django的後臺顯示
能夠看到獲取到的版本號是V2
當咱們在url中沒有傳參數版本就會顯示默認版本如訪問:http://127.0.0.1:8000/api/users/
這個在上面咱們設置了它的默認版本是v1因此這裏顯示v1
當咱們url傳的版本再也不setting設置的範圍中就會報錯
如:http://127.0.0.1:8000/api/users/?version=v3
一般狀況我門應該用URLPATH的方式,而不是用前面GET()傳參方式
url裏面經過正則表達式定義哪些版本,
一、修改api/urls.py,這個裏面獲取版本也能夠放在Myproject.py下面,看我的的喜愛
from django.conf.urls import url, include from .views import UserView # 當咱們不知道格式的時候能夠去 # from rest_framework import versioning中去查看 # 進入到versioning中找到 class URLPathVersioning(BaseVersioning):的類裏面就有教你如何使用 urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', UserView.as_view()), ]
二、api/views.py
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.request import Request from rest_framework.versioning import URLPathVersioning class UserView(APIView): versioning_class = URLPathVersioning def get(self,request,*args,**kwargs): #獲取版本 print(request.version) return HttpResponse('用戶列表')
這個URLPathVersioning咱們能夠放到settings裏面,全局配置,就不用寫到views裏面,每一個類都要寫一遍了
settings.py
# 版本 # REST_FRAMEWORK = { # "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", # "DEFAULT_VERSION":'v1', #默認的版本 # "ALLOWED_VERSIONS":['v1','v2'], #容許的版本 # "VERSION_PARAM":'version' #get方式url中參數的名字 ?version=xxx # } #全局 REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", }
這個時候的api/views.py爲
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.request import Request class UserView(APIView): def get(self,request,*args,**kwargs): #獲取版本 print(request.version) return HttpResponse('用戶列表')
瀏覽器訪問:http://127.0.0.1:8000/api/v1/users/
一、api/urls.py
from django.conf.urls import url, include from .views import UserView # 當咱們不知道格式的時候能夠去 # from rest_framework import versioning中去查看 # 進入到versioning中找到 class URLPathVersioning(BaseVersioning):的類裏面就有教你如何使用 urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', UserView.as_view(), name='api_user'), ]
二、api/views.py
from django.shortcuts import render, HttpResponse from rest_framework.views import APIView from rest_framework.request import Request class UserView(APIView): def get(self, request, *args, **kwargs): # 獲取版本 print('version', request.version) # 獲取處理版本的對象 print('versioning_scheme', request.versioning_scheme) # 獲取瀏覽器訪問的url,reverse反向解析 # 須要兩個參數:viewname就是url中的別名,request=request是url中要傳入的參數 # (?P<version>[v1|v2]+)/users/,這裏原本須要傳version的參數,可是version包含在request裏面(源碼裏面能夠看到),全部只須要request=request就能夠 url_path = request.versioning_scheme.reverse(viewname='api_user', request=request) print('url_path', url_path) # self.dispatch return HttpResponse('用戶列表')
瀏覽器訪問:http://127.0.0.1:8000/api/v1/users/
會看到如下結果:
上面的方法推薦使用URLPATH這種版本號。
一、api/urls.py
from django.conf.urls import url, include from .views import UserView,PaserView # 當咱們不知道格式的時候能夠去 # from rest_framework import versioning中去查看 # 進入到versioning中找到 class URLPathVersioning(BaseVersioning):的類裏面就有教你如何使用 urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/users/$', UserView.as_view(), name='api_user'), url(r'paser/', PaserView.as_view(), ), # 解析 ]
二、api/views.py
from django.shortcuts import render, HttpResponse from rest_framework.views import APIView from rest_framework.request import Request class UserView(APIView): def get(self, request, *args, **kwargs): # 獲取版本 print('version', request.version) # 獲取處理版本的對象 print('versioning_scheme', request.versioning_scheme) # 獲取瀏覽器訪問的url,reverse反向解析 # 須要兩個參數:viewname就是url中的別名,request=request是url中要傳入的參數 # (?P<version>[v1|v2]+)/users/,這裏原本須要傳version的參數,可是version包含在request裏面(源碼裏面能夠看到),全部只須要request=request就能夠 url_path = request.versioning_scheme.reverse(viewname='api_user', request=request) print('url_path', url_path) # self.dispatch return HttpResponse('用戶列表') from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser class PaserView(APIView): parser_classes = [JSONParser, FormParser] # 一共有上面4種方式,可是經常使用的就是下面2種方式,同時默認的也是三種方式JSONParser, FormParser, MultiPartParser # 如何查看能夠在APIView下找到api_settings裏面的DEFAULTS裏面能夠看到默認的是三種。 # JSONParser:表示只能解析content-type:application/json的頭 # FormParser:表示只能解析content-type:application/x-www-form-urlencoded的頭 def post(self, request, *args, **kwargs): # 獲取解析後的結果 print(request.data) return HttpResponse('paser')
若是全局使用某一個解析器的話在setting裏面
#全局配置 REST_FRAMEWORK = { #版本 "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", #解析器 "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"] }
上面咱們實驗要藉助postman這個軟件來完成測試
在咱們前面說到的序列化的最後一個版本(能夠看關於restforamework的第一篇文章)
urls.py的代碼以下所示
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/$', views.BookViewSet.as_view({"get": "list", "post": "create"}), name="book_list"), url(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' }), name="book_detail"), ]
這個時候當咱們有多個url的時候就要寫多個這個時候就顯得不是很智能因此這裏使用了restframework的路由系統,這個系統就是針對上面的路由的
上面的urls.py改爲以下
from django.conf.urls import url, include from rest_framework import routers from app01 import views router = routers.DefaultRouter() router.register('books', views.BookViewSet) urlpatterns = [ url(r'^',include(route.urls)), url(r'^(?P<version>[v1|v2]+)/users/$', UserView.as_view(), name='api_user'), ]
上面就會幫咱們生成開始的兩條url外還會幫咱們生成一下2條url,一共有四條
^books\.(?P<format>[a-z0-9]+)/?$ [name='books-list'] ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='books-detail']
上面的第一個url對應下面的訪問
咱們訪問http://127.0.0.1:8000/books/?format=josn或者http://127.0.0.1:8000/books.json
他返回的是一個json數據想要什麼數據就在後面寫上前提是他要支持這個數據。
上面的第二個url
咱們訪問http://127.0.0.1:8000/book/1/?format=josn或者http://127.0.0.1:8000/1/books.json
理解和上面是同樣的。
一、urls.py
from django.conf.urls import url, include from .views import Pager1View urlpatterns = [ url(r'(?P<version>[v1|v2]+)/page1/', Pager1View.as_view(),) #分頁1 ]
二、api/utils/serializers/pager.py
from rest_framework import serializers from api import models class PagerSerialiser(serializers.ModelSerializer): class Meta: model = models.Role fields = "__all__"
三、api/views.py
from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination from rest_framework.views import APIView from api import models class Pager1View(APIView): def get(self, request, *args, **kwargs): # 獲取全部數據 roles = models.Role.objects.all() # 建立分頁對象 pg = PageNumberPagination() # 獲取分頁的數據 page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) # 對數據進行序列化 ser = PagerSerialiser(instance=page_roles, many=True) return Response(ser.data)
四、settings配置
REST_FRAMEWORK = { # 分頁 "PAGE_SIZE": 2 # 每頁顯示多少個 }
在數據庫裏面添加幾條數據
訪問:http://127.0.0.1:8000/api/v1/page1/?page=2
from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination from rest_framework.views import APIView from api import models # 自定義分頁類 class MyPageNumberPagination(PageNumberPagination): # 每頁顯示多少個 page_size = 3 # 默認每頁顯示3個,能夠經過傳入pager1/?page=2&size=4,改變默認每頁顯示的個數 page_size_query_param = "size" # 最大頁數不超過10 max_page_size = 10 # 獲取頁碼數的 page_query_param = "page" class Pager1View(APIView): def get(self, request, *args, **kwargs): # 獲取全部數據 roles = models.Role.objects.all() # 建立分頁對象,這裏是自定義的MyPageNumberPagination pg = MyPageNumberPagination() # 獲取分頁的數據 page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) # 對數據進行序列化 ser = PagerSerialiser(instance=page_roles, many=True) return Response(ser.data)
訪問:http://127.0.0.1:8000/api/v1/page1/?page=1&size=2
上面咱們默認是顯示三個數據可是我在訪問的時候本身設置爲2個因此頁面顯示的是2個數據
from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import LimitOffsetPagination from rest_framework.views import APIView from api import models # 自定義分頁類 class MyLimitOffsetPagination(LimitOffsetPagination): # 默認顯示的個數 default_limit = 2 # 當前的位置 offset_query_param = "offset" # 經過limit改變默認顯示的個數 limit_query_param = "limit" # 一頁最多顯示的個數 max_limit = 10 class Pager1View(APIView): def get(self, request, *args, **kwargs): # 獲取全部數據 roles = models.Role.objects.all() # 建立分頁對象 pg = MyLimitOffsetPagination() # 獲取分頁的數據 page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) # 對數據進行序列化 ser = PagerSerialiser(instance=page_roles, many=True) return Response(ser.data)
訪問:http://127.0.0.1:8000/api/v1/page1/?offset=1&limit=1
咱們在返回的時候能夠使用get_paginated_response方法這樣就會獲得上一頁和下一頁的url
訪問:http://127.0.0.1:8000/api/v1/page1/?limit=1&ofset=1
這個適用於上面2種分頁方式
加密分頁方式,只能經過點「上一頁」和下一頁訪問數據
from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import CursorPagination from rest_framework.views import APIView from api import models # 自定義分頁類 class MyCursorPagination(CursorPagination): cursor_query_param = "cursor" page_size = 2 #每頁顯示2個數據 ordering = 'id' #排序 page_size_query_param = None max_page_size = None class Pager1View(APIView): def get(self,request,*args,**kwargs): #獲取全部數據 roles = models.Role.objects.all() #建立分頁對象 pg = MyCursorPagination() #獲取分頁的數據 page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) #對數據進行序列化 ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data)
咱們訪問:http://127.0.0.1:8000/api/v1/page1/
點擊紅色部位會看到以下部分。
咱們能夠看到如今只能點擊上一頁不可以點擊下一頁。由於數據只有2頁。
咱們直接輸入:http://127.0.0.1:8000/api/v1/page1/?cursor=2
會出現上面的錯誤提示由於該分頁使用的是加密。
若是咱們使用的序列化是最終極版本的如:
from rest_framework import viewsets from app01.models import * from app01.utils.serializers import * class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() # BookModelSerializers和前面的同樣沒什麼變化功能相似於modelform serializer_class = BookModelSerializers
如何使用分頁只須要在代碼中添加:
from rest_framework import viewsets from app01.models import * from app01.utils.serializers import * from rest_framework.pagination import CursorPagination class MyCursorPagination(CursorPagination): cursor_query_param = "cursor" page_size = 2 # 每頁顯示2個數據 ordering = 'id' # 排序 page_size_query_param = None max_page_size = None class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() # BookModelSerializers和前面的同樣沒什麼變化功能相似於modelform serializer_class = BookModelSerializers pagination_class = MyCursorPagination
上面的 MyCursorPagination就是咱們自定義的分頁組件。