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就是咱们自定义的分页组件。

相关文章
相关标签/搜索