一、url控制
1.1、自定义(原始)
路由一般写法如下
FBV:
url(r'^site/', views.site), url(r'^site/(?P<name>\w+)/', views.site)
CBV:
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()), ]
1.2、继承了ModelViewSet的视图的路由写法
本质是继承了ViewSetMixin,这个类重写了as_view()方法
路由 :
from django.conf.urls import url
from django.contrib import admin
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'
}))
]
序列化
from rest_framework.serializers import ModelSerializer
from app01 import models
class PublishSerializers(ModelSerializer):
class Meta:
model = models.Publish
fields = '__all__'
视图
from rest_framework.viewsets import ModelViewSet
from app01 import models
from app01.serializer import PublishSerializers
class PublishView(ModelViewSet):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
1.3、自动生成路由(必须继承ModelViewSet类)
生成路由需要导入SimpleRouter,DefaultRouter两个类
- SimpleRouter 自动生成两条路由
- DefaultRouter自动生成四条路由
路由:
from django.conf.urls import url, include
from django.contrib import admin
from app01 import views
from rest_framework.routers import SimpleRouter, DefaultRouter
router = SimpleRouter()
router.register('publish', views.PublishView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include(router.urls))
]
可以通过如下方式访问(指定format=json拿到的就是json格式的数据):
http://127.0.0.1:8000/publish/?format=json
http://127.0.0.1:8000/publish/1/?format=json
http://127.0.0.1:8000/publish/
http://127.0.0.1:8000/publish/1/
视图:与第二种的一样,只是路由是自己生成
from rest_framework.viewsets import ModelViewSet
from app01 import models
from app01.serializer import PublishSerializers
class PublishView(ModelViewSet):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
如果用DefaultRouter生成路由,可以直接点访问(直接拿到的就是json格式的数据,而不是页面):
http://127.0.0.1:8000/publish/1.json
http://127.0.0.1:8000/publish.json
二、解析器
根据请求头 content-type 选择对应的解析器对请求体内容进行处理。
有application/json,x-www-form-urlencoded,form-data等格式。
一般不需要改动,项目最开始全局配置一下就行了,作用是控制视图类能够解析前端传过来的格式是什么样的。
三种编码格式:urlencoded,formdata,json
-urlencoded:在body体中的格式是:name=lqz&age=18&wife=liuyifei
-formdata:在body体中的格式数据部分跟文件部分有区分
-json格式:在body体中就是json格式
2.1、全局使用
在settings配置文件中配置即可全局使用
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser' # 对应application/json
'rest_framework.parsers.FormParser' # 对应application/x-www-form-urlencoded
'rest_framework.parsers.MultiPartParser' # 对应multipart/form-data
]
}
路由
url(r'^test/', views.Test.as_view())
视图
from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
def post(self, request, *args, **kwargs):
print(request.content_type)
# 获取请求的值,并使用对应的parser进行处理
print(request.data)
# 格式为application/json或x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('post响应内容')
def put(self, request, *args, **kwargs):
return Response('put响应内容')
2.2、局部使用
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser parser_classes = [JSONParser,]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
class Test(APIView):
parser_classes = [JSONParser,] # 除了json格式,发其他的request.POST都为空
def post(self, request, *args, **kwargs):
print(request.content_type)
# 获取请求的值,并使用对应的parser进行处理
print(request.data)
# 格式为application/json或x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('post响应内容')
def put(self, request, *args, **kwargs):
return Response('put响应内容')
2.3、源码分析
在调用request.data时,才开始解析。
查看self._load_data_and_files()方法,看见这句代码:self._data, self._files = self._parse(),到parse里面看看
查看self.negotiator.select_parser(self, self.parsers)
最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
三、响应器
3.1、作用
根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。这个一般不用改,全局配置即可
用户请求URL:
http://127.0.0.1:8000/test/?format=json
http://127.0.0.1:8000/test.json
3.2、 内置渲染器
显示json格式:JSONRenderer
访问URL:
- http://127.0.0.1:8000/test/?format=json
- http://127.0.0.1:8000/test.json
- http://127.0.0.1:8000/test/
默认显示格式:BrowsableAPIRenderer(可以修改它的html文件)
访问URL:
- http://127.0.0.1:8000/test/?format=api
- http://127.0.0.1:8000/test.api
- http://127.0.0.1:8000/test/
表格方式:AdminRenderer
访问URL:
- http://127.0.0.1:8000/test/?format=admin
- http://127.0.0.1:8000/test.admin
- http://127.0.0.1:8000/test/
form表单方式:HTMLFormRenderer
访问URL:
- http://127.0.0.1:8000/test/?format=form
- http://127.0.0.1:8000/test.form
- http://127.0.0.1:8000/test/
3.3、全局使用
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer']
}
3.4、局部使用
在视图类中配置即可
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import AdminRenderer,JSONRenderer,BrowsableAPIRenderer
class Test(APIView):
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
def get(self, request, *args, **kwargs):
return Response('get响应内容')
注意:如果同时多个存在时,自动根据URL后缀来选择渲染器。
四、版本控制
4.1、内置的版本控制类
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/
4.2、局部使用
注意:版本控制的局部使用不是列表传多个,而是只能有一种方法控制
# 在CBV类中加入
versioning_class = URLPathVersioning
路由:
url(r'^(?P<version>[v1|v2]+)/test/', views.Test.as_view()),
视图:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning
class Test(APIView):
versioning_class = URLPathVersioning
def get(self, request, *args, **kwargs):
if request.version == 'v1':
return Response('V1版本的代码')
return Response('V2版本的代码')
访问http://127.0.0.1:8000/v1/test/,根据对应的版本,做出不同的响应。
4.3、全局使用
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值)
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version' # URL中获取值的key
}
4.4、源码分析
首先是走的APIView类的as_view()方法,然后到他的dispatch()方法,再进入到self.initial()方法,可以看到它内部有下面的版本控制的代码
我们找找APIView的determine_version方法看看
我配的是这个URLPathVersioning类(先看我自己配置的,如果没有就去配置文件找),给它加括号实例化,调用自己的determine_version方法:
执行完上面的步骤又回到了APIView的determine_version方法,然后执行完将结果返回给self.initial()方法
![]()
五、分页器
先来准备点数据
models.py
from django.db import models class Publish(models.Model): name=models.CharField(max_length=32) city=models.CharField(max_length=64)
批量插入
# 批量插入数据 def insert(): ls = [] for i in range(100): ls.append(models.Publish(name='%s出版社' % i, city='%s城市' % i)) models.Publish.objects.bulk_create(ls)
序列化数据
from rest_framework.serializers import ModelSerializer from app01 import models class PublishSerializers(ModelSerializer): class Meta: model = models.Publish fields = '__all__'
5.1、常规分页
视图:分页(查看第n页,每页显示n条)
from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
class PublishView(APIView):
def get(self, request, *args, **kwargs):
# 查询所有数据
res = models.Publish.objects.all()
# 实例化产生一个普通分页对象
page = PageNumberPagination()
# 指定每页显示多少条
page.page_size = 10
# 指定查询哪一页的key值
page.page_query_param = 'xxx'
# 前端控制每页显示多少条的查询key值比如size=9,表示一页显示9条
page.page_size_query_param = 'size'
# 控制每页最大显示多少,size如果传100,最多也是显示指定的条数
page.max_page_size = 10
res_page = page.paginate_queryset(res, request, self)
# 序列化
pub_ser = PublishSerializers(instance=res_page, many=True)
# 去settings中配置每页显示多少条:'PAGE_SIZE':2 #表示每页显示两条
# return Response(pub_ser.data)
# 返回的结果中带了总条数,上一页下一页的链接
return page.get_paginated_response(pub_ser.data)
在配置文件中配置每页显示多少条,其实我们在视图里已经写了,配置文件的配不配都行
REST_FRAMEWORK = {
# "DEFAULT_PARSER_CLASSES":[
# 'rest_framework.parsers.JSONParser',
# ],
'PAGE_SIZE': 10 # 表示每页显示十条
}
路由:
url(r'^publish/', views.PublishView.as_view())
5.2、偏移分页(在第n个位置,向后查看n条数据)
from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import LimitOffsetPagination
class PublishView(APIView):
def get(self, request, *args, **kwargs):
res = models.Publish.objects.all()
# 实例化一个偏移分页对象
page = LimitOffsetPagination()
"""四个参数"""
# 从标杆位置往后取几个,默认取三个,可以指定
page.default_limit = 3
# 每次取的条数
page.limit_query_param = 'limit'
# 标杆值,现在偏移到哪个位置,如果offset=6,表示当前在第6条位置上,往后取limit=多少条
page.offset_query_param = 'offset'
# 最大取10条
page.max_limit = 10
res_page = page.paginate_queryset(res, request, self)
# 序列化
pub_ser = PublishSerializers(res_page, many=True)
"""到settings配置每页显示多少条"""
return page.get_paginated_response(pub_ser.data)
5.3、cursor游标方式分页
只能看上一页和下一页,速度快
from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import CursorPagination
class PublishView(APIView):
def get(self, request, *args, **kwargs):
res = models.Publish.objects.all()
# 实例化产生一个游标分页对象
page = CursorPagination()
"""三个参数"""
# 每页显示的大小
page.page_size = 3
# 查询的key值
page.cursor_query_param = 'cursor'
# 按什么排序
page.ordering = 'id'
res_page = page.paginate_queryset(res, request, self)
# 序列化
pub_ser = PublishSerializers(instance=res_page, many=True)
"""到settings配置每页显示多少条,可配可不配"""
# return Response(pub_ser.data)
return page.get_paginated_response(pub_ser.data)