url,解释器,响应器,版本控制,分页

Posted huangxuanya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了url,解释器,响应器,版本控制,分页相关的知识,希望对你有一定的参考价值。

路由控制

-基本路由写法:咱们一直写的??
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r^books/$, views.BookView.as_view()),
    url(r^books/(?P<pk>\\d+)$, views.BookDetailView.as_view()),
]
class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        bs = BookSerializers(book_list, many=True)
        return Response(bs.data)

    def post(self, request):
        # 添加一条数据
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return Response(bs.data)
        else:

            return Response(bs.errors)

class BookDetailView(APIView):
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(data=request.data,instance=book_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response("")
-第二种写法(必须继承只要继承了ViewSetMixin):??
from app01 import views
urlpatterns = [
    url(r^admin/, admin.site.urls),
  获取所有出版社,以及新增数据 url(r
publish/$,views.PublishView.as_view(get:list,post:create)),
  获取单个数据,删除单个数据,更新单个数据 url(r
publish/(?P<pk>\\d+)$,views.PublishView.as_view(get:retrieve,delete:destroy,put:update)) ]

注意:?

1.‘get‘,‘post‘,‘delete‘,‘put‘,‘‘是method提交数据的方法,list,create,retrieve,destroy,update是内部对应的方法,可以在视图类中重写这些方法

2.五个方法,两个路由

技术图片
from rest_framework .serializers import ModelSerializer
from app01 import models
class PublishSerializers():
    class Meta:
        model=models.Publish
        fields=__all__
serializer.py
技术图片
from django.db import models

# Create your models here.
class Publish(models.Model):
    name=models.CharField(max_length=32)
    city = models.CharField(max_length=64)
models.py
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers
#源码

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

1.ModelViewSet中继承了ViewSetMixin所有继承了GenericViewSet,GenericViewSet继承了ViewSetMixin

2.ViewSetMixin中action必须要传值,不然会报错(action也就是传入的字典)

3.技术图片

4.有名分组,传入的关键字必须是pk,这个内部固定死的

??????????完美分割线??????????

技术图片

通过format=json获取到json格式的字符串
也有另外一种方式(就是需要配置路由)
url(r‘^publish\\.(?P<format>\\w+)$‘, views.PublishView.as_view(‘get‘:‘list‘,‘post‘:‘create‘))

技术图片


-第三种(自动生成路由,必须继承ModelViewSet):?
-SimpleRouter 自动生成两条路由
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register(publish,views.PublishView)

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # url(r‘^publish/$‘,views.PublishView.as_view(‘get‘:‘list‘,‘post‘:‘create‘)),
    # url(r‘^publish/(?P<pk>\\d+)‘,views.PublishView.as_view(‘get‘:‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘)),
    url(r‘‘,include(router.urls))
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers
   -DefaultRouter自动生成四条路由
from django.conf.urls import url,include
from app01 import views
from rest_framework import routers
router=routers.DefaultRouter()
# 两个参数,一个是匹配的路由,一个是视图中写的CBV的类
router.register(publish,views.PublishView)
urlpatterns = [
    # http://127.0.0.1:8000/publish/format=json(渲染器通过这个判断,返回渲染的页面)
    # url(r‘^publish/‘, views.PublishView.as_view(‘get‘:‘list‘,‘post‘:‘create‘)),
    # http://127.0.0.1:8000/publish.json(渲染器通过这个判断,返回渲染的页面)
    # url(r‘^publish\\.(?P<format>\\w+)$‘, views.PublishView.as_view(‘get‘:‘list‘,‘post‘:‘create‘)),
    
    # 可以用 以下方式访问
    # 1 http://127.0.0.1:8000/publish/
    # 2 http://127.0.0.1:8000/publish.json
    # 3 http://127.0.0.1:8000/publish/3
    # 4 http://127.0.0.1:8000/publish/3.json   
    url(r‘‘,include(router.urls))
]
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

 

解析器

-在取某个值之前,先反射看一下有没有,有的话直接返回,如果没有,再去执行获取这个值的方法
一开始request.data去获取值,先看看你之前是否用过,用过直接返回,没用过就去body取出做解析,所以入口是request.data
from rest_framework.views import APIView
from rest_framework.response import  Response
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
from rest_framework.request import Request
class Test(APIView):
    parser_classes = [JSONParser,]
    def post(self,request):
        print(request.data)
        print(type(request.data))
        return Response

从Request中找到data

源码??

技术图片

技术图片

技术图片

parser就是我在视图类中parser_classes=[JSONParser,]JSONParser类产生的对象

然后调用parser对象方法进行解析(以下是在Requst类中的_parser方法中找到的)

技术图片

这些类中都有一个parse方法,称之为鸭子类型,

不管返回的是谁的对象,直接调用它们类中的parser方法传入该传的参数就能做解析

技术图片

技术图片

Request类中_parser中的parser = self.negotiator.select_parser(self,self.parsers)中的negotiator是Request初始化对象的时候产生并传入值,而Request是在APIVeiw 的dispatch中初始化对象的

技术图片

Request类中_parser中的parser = self.negotiator.select_parser(self,self.parsers)中的self.parsers

是Request初始化对象的时候产生并传入值,而Request是在APIVeiw 的dispatch中初始化对象的

而parsers = self.get_parsers()中的get_parsers,就是传入视图中定义的列表中的类名

技术图片

然后parser = self.negotiator.select_parser(self,self.parsers)中的self.parsers是所有解析器,然后选择一个返回,根据Request对象request请求编码格式传入

小总结:??

-解析器(一般不需要动,项目最开始全局配置一下就可以了) 
-作用是控制我的视图类能够解析前端传过来的格式是什么样的
-全局使用:
在setting中配置:
REST_FRAMEWORK =
"DEFAULT_PARSER_CLASSES":[
‘rest_framework.parsers.JSONParser‘,
]


-全局使用:
-在视图类中:
parser_classes=[JSONParser,]

-源码流程:
-当调用request.data的时候去执行解析方法----》根据传过来的编码方式选择一个解析器对象,调用解析器对象的parser方法完成解析

响应器

-响应器 
-from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
-不用动,就用全局配置即可
-全局使用:
-在setting中配置
‘DEFAULT_RENDERER_CLASSES‘:[xxx,xxx]
-局部使用:
-在视图类中配置:
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]

版本控制

在restful规范当中,版本号可以放在路径当中,还可以放在请求头当中

直接使用内置,

内置的版本控制类

技术图片
from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderVersioning,NamespaceVersioning,URLPathVersioning

#基于url的get传参方式:QueryParameterVersioning------>如:/users?version=v1
#基于url的正则方式:URLPathVersioning------>/v1/users/
#基于 accept 请求头方式:AcceptHeaderVersioning------>Accept: application/json; version=1.0
#基于主机名方法:HostNameVersioning------>v1.example.com
#基于django路由系统的namespace:NamespaceVersioning------>example.com/v1/users/
技术图片

技术图片

局部使用

#在CBV类中加入
versioning_class = URLPathVersioning

四 全局使用

技术图片
REST_FRAMEWORK = 
    ‘DEFAULT_VERSIONING_CLASS‘:‘rest_framework.versioning.QueryParameterVersioning‘,
    ‘DEFAULT_VERSION‘: ‘v1‘,            # 默认版本(从request对象里取不到,显示的默认值)
    ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘],   # 允许的版本
    ‘VERSION_PARAM‘: ‘version‘          # URL中获取值的key
技术图片

示例

基于正则的方式:

技术图片
from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r^(?P<version>[v1|v2]+)/test/, TestView.as_view(), name=test),
]
urls.py
技术图片
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning


class TestView(APIView):
    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)

        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse(test, request=request)
        print(reverse_url)

        return Response(GET请求,响应内容)
views.py
技术图片
        # 基于django内置,反向生成url
        from django.urls import reverse
        url2=reverse(viewname=ttt,kwargs=version:v2)
        print(url2)
View Code

分页

批量添加(了解)

class PublishView(APIView):
    versioning_class = URLPathVersioning
    parser_classes = [JSONParser,]

    def get(self,request,*args,**kwargs):
        li = []
        for i in range(100):
           li.append(models.Publish(name=%s出版社%i,city=%s城市%i))
           models.Publish.objects.bulk_create(li)
        return Response()
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^(?P<version>[v1|v2]+)/test/, views.PublishView.as_view())
]

简单分页(查看第n页,每页显示n条)

# 一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
from rest_framework.versioning import URLPathVersioning
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
class Page(APIView):def get(self,request,*args,**kwargs): #查询出所有的数据 ret = models.Publish.objects.all() #实例化产生一个普通分页对象 page=PageNumberPagination() #ret_page是返回分页之后的数据(列表存放着我一个个数据),已经是分好页了 ret_page = page.paginate_queryset(ret,request,self) #序列化 pub_ser = serializer.PublishSerializers(ret_page,many=True) #去settings中配置每页显示多少条 return Response(pub_ser.data)
REST_FRAMEWORK = 
    "DEFAULT_PARSER_CLASSES":[
        rest_framework.parsers.JSONParser,
    ],

    PAGE_SIZE:2   #表示每页显示两条


技术图片自定义页数

偏移分页(在第n个位置,向后查看n条数据)

技术图片
# http://127.0.0.1:8000/pager/?offset=4&limit=3
from rest_framework.pagination import LimitOffsetPagination
# 也可以自定制,同简单分页
class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=LimitOffsetPagination()
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # return page.get_paginated_response(ser.data)
        return Response(ser.data)
技术图片

CursorPagination(加密分页,只能看上一页和下一页,速度快)

思考:不重写类,修改类属性?

技术图片
from rest_framework.pagination import CursorPagination
# 看源码,是通过sql查询,大于id和小于id
class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=CursorPagination()
        page.ordering=‘nid‘
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # 可以避免页码被猜到
        return page.get_paginated_response(ser.data)

小总结:??

-分页
1 常规分页
-基本使用:
-page=PageNumberPagination实例化产生对象
-返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,
-再序列化,序列化该返回值
-四个参数
#每页显示多少条
page.page_size=3
#查询指定查询哪一页的key值
page.page_query_param=‘xxx‘

#前端控制每页显示多少条的查询key值比如size=9,表示一页显示9条
page.page_size_query_param=‘size‘
#控制每页最大显示多少,size如果传100,最多也是显示10
page.max_page_size=10
2 偏移分页
-基本使用:
-page=LimitOffsetPagination实例化产生对象
-返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,
-再序列化,序列化该返回值

-四个参数:
#从标杆位置往后取几个,默认取3个,我可以指定
page.default_limit=3
#每次取得条数
page.limit_query_param=‘limit‘
#标杆值,现在偏移到哪个位置,如果offset=6 表示当前在第6条位置上,往后取
page.offset_query_param=‘offset‘
#最大取10条
page.max_limit=10
3 cursor游标方式
-基本使用:
-page=CursorPagination实例化产生对象
-返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,
-再序列化,序列化该返回值

-三个参数:
#每页显示的大小
page.page_size=3
#查询的key值

三种编码格式:urlencoded,formdata,json
-urlencoded:在body体中的格式是:name=lqz&age=18&wife=liuyifei
-formdata:在body体中的格式数据部分跟文件部分有区分
-json格式:在body体中就是json格式

page.cursor_query_param=‘cursor‘
# 按什么排序
page.ordering=‘id‘
-注意:get_paginated_response:调用这个方法返回的数据中会有总条数,上一页地址,下一页地址

以上是关于url,解释器,响应器,版本控制,分页的主要内容,如果未能解决你的问题,请参考以下文章

Django框架深入了解_04(DRF之url控制解析器响应器版本控制分页)

路由控制,版本控制,解析器,响应器

(了解)rest_framework之版本控制, 响应器, url控制器

路由控制和响应器

DjangoRestFramework学习三之认证组件权限组件频率组件url注册器响应器分页组件

解析器,路由控制,响应器