Django rest-framework後續

版本

新建一個工程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)
api/models.py

二、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')),
]
Myproject/urls.py

三、api/urls.pyapi

from django.conf.urls import url, include
from .views import UserView

urlpatterns = [
    url('users/', UserView.as_view()),
]
api/urls.py

四、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('用戶列表')
api/views.py

五、settings.pysession

#版本
REST_FRAMEWORK = {
    "DEFAULT_VERSION":'v1',               #默認的版本
    "ALLOWED_VERSIONS":['v1','v2'],       #容許的版本
    "VERSION_PARAM":'version'             #GET方式url中參數的名字  ?version=xxx
}
settings.py

同時咱們是經過網頁測試的,因此在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

2.在URLPATH中獲取

一般狀況我門應該用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/urls.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 URLPathVersioning

class UserView(APIView):

    versioning_class = URLPathVersioning

    def get(self,request,*args,**kwargs):
        #獲取版本
        print(request.version)
        return HttpResponse('用戶列表')
api/views.py

這個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",
}
settings.py

 這個時候的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('用戶列表')
api/views.py

瀏覽器訪問:http://127.0.0.1:8000/api/v1/users/

反向解析訪問的url

一、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/urls.py

 二、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('用戶列表')
api/views.py

瀏覽器訪問: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/urls.py

 

 二、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')
api/views.py

 

 

若是全局使用某一個解析器的話在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"),
]
View Code

 

這個時候當咱們有多個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'),
]
View Code

 

 

 上面就會幫咱們生成開始的兩條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個數據

第二種分頁   LimitOffsetPagination

 

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種分頁方式

第三種分頁 CursorPagination

加密分頁方式,只能經過點「上一頁」和下一頁訪問數據

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就是咱們自定義的分頁組件。

相關文章
相關標籤/搜索