drf 下的 url控制 解析器 响应器 版本控制 分页
一、url 控制 前戏准备: models.py: class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() hobby = models.IntegerField(choices=((1,'basketball'),(2,'soccer'),(3,'baseball')),default=1) class Book(models.Model): title = models.CharField(max_length=32) publish = models.CharField(max_length=32) create_time = models.DateTimeField(auto_now_add=True) author = models.ManyToManyField(to='Author') 自定义文件下:Myserializer.py from app01 import models from rest_framework.serializers import ModelSerializer,Serializer,SerializerMethodField from rest_framework import serializers class AuthorSerializer(ModelSerializer): class Meta: model = models.Author fields = '__all__' # 可以解决choice字段前端可以取道想要的表示数据,发到后端的时候,发对应的序号就行,好用 hobby = serializers.SerializerMethodField() def get_hobby(self,obj): return obj.get_hobby_display() class BookSerializer(ModelSerializer): class Meta: model = models.Book fields = '__all__' 视图层 from app01 import models from app01.MyseriaLizer import AuthorSerializer ,BookSerializer from rest_framework.viewsets import ModelViewSet class Author(ModelViewSet): queryset = models.Author.objects.all() serializer_class = AuthorSerializer class Book(ModelViewSet): queryset = models.Book.objects.all() serializer_class = BookSerializer 路由层: from django.conf.urls import url,include from django.contrib import admin from app01 import views from rest_framework.routers import SimpleRouter,DefaultRouter #使用 Simplerouter 自动生成两种路由 router = SimpleRouter() router.register('book',views.Book) router.register('author',views.Author) #多个路由直接再注册一次就ok url(r'',include(router.urls)) 其自动生成的路径为: ^book/$ [name='book-list'] ^book/(?P<pk>[^/.]+)/$ [name='book-detail'] ^author/$ [name='author-list'] ^author/(?P<pk>[^/.]+)/$ [name='author-detail'] #使用 DefaultRouter 自动生成6种路由 router = DefaultRouter() #用法一样,将类换一下即可 router.register('book',views.Book) url(r'',include(router.urls)) 其自动生成的路径: ^book/$ [name='book-list'] ^book\.(?P<format>[a-z0-9]+)/?$ [name='book-list'] ^book/(?P<pk>[^/.]+)/$ [name='book-detail'] ^book/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail'] ^$ [name='api-root'] ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
二、解析器 -解析器(一般不需要动,项目最开始全局配置一下就可以了) -作用是控制我的视图类能够解析前端传过来的格式是什么样的 在视图层使用 from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class Author(ModelViewSet): renderer_classes = [JSONRenderer,] #局部使用 queryset = models.Author.objects.all() serializer_class = AuthorSerializer 全局使用: 先在settings里配置: REST_FRAMEWORK = { "DEFAULT_PARSER_CLASSES":[ 'rest_framework.parsers.JSONParser', ] } 局部使用:直接在视图类中使用:parser_classes=[JSONParser,]
三、版本控制 用来版本的控制 drf内置的版本控制类: 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.URLPathVersioning', 'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version' # URL中获取值的key } 路由层: urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'), ] 视图层: 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请求,响应内容') 补充: # 基于django内置,反向生成url from django.urls import reverse url2=reverse(viewname='ttt',kwargs={'version':'v2'}) print(url2)
批量插入数据: def get(self,request,*args,**kwargs): li = [] for i in range(100): li.append(models.Test(classes='%s班级'%i,grade='第%s人'%i)) models.Test.objects.bulk_create(li) return Response()
四、分页器 常规分页: 基本使用: from rest_framework.pagination import PageNumberPagination class Test(APIView): def get(self,request,*args,**kwargs): #获得所有要分页的数据 ret = models.Test.objects.all() # 实例化产生对象 page = PageNumberPagination() # 控制每页显示的条数 page.page_size = 5 # 这一步也可交给settings配置,不过需要记住优先顺序! # 指定查询哪一页的key值,在url后输入即可,记得带上? page.page_query_param = 'page' 前端控制每页显示多少条的查询key值 可以改变改变默认值 page.page_size_query_param = 'size' # 控制每页最多显示的条数 page.max_page_size = 10 #在数据库中获取分页的数据 ret_page = page.paginate_queryset(ret,request,view=self) test_ser = TestSerializer(instance=ret_page,many=True) # return Response(test_ser.data) 正常使用 #这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数 return page.get_paginated_response(ser.data)
路由层: url(r'^test/',views.Test.as_view()) 自定义序列化层: class TestSerializer(ModelSerializer): class Meta: model = models.Test fields = '__all__' #exclude = (当前的不会出现,其他的会有的) 注:在使用过程中发现 :会报错,但不影响代码的执行 UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list 经过google查询资料,发现是获取所有queryset对象时没有排序! 因此只需要获取数据时: ret = models.Test.objects.all().order_by('pk')即可
对于上述default_limit配置无效的解决:
注意代码的顺序:即将
ret_page = page.paginate_queryset(ret, request, view=self)
test_ser = TestSerializer(instance=ret_page,many=True)
放置最后即可!
偏移分页: LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination
class Test(APIView):
def get(self, request, *args, **kwargs):
ret = models.Test.objects.all().order_by('pk')
# 实例化产生对象
page = LimitOffsetPagination()
# 固定写法
ret_page = page.paginate_queryset(ret,request,view=self)
# page.default_limit = 2 不知为何,这种配置没用,只能手动指定 limit 的数字,显示多少条
page.limit_query_param = 'limit'
#标杆值,现在偏移到哪个位置
page.offset_query_param = 'offset'
# 最大往后去的条数
page.max_limit = 10
test_ser = TestSerializer(instance=ret_page,many=True)
return Response(test_ser.data)
加密分页 :只能看上一页,下一页,查询速度快 CursorPagination
from rest_framework.pagination import CursorPagination
class Test(APIView):
def get(self,request,*args,**kwargs):
page = CursorPagination()
ret = models.Test.objects.all()
# 每页显示的大小
page.page_size = 3
#查询的key值
page.cursor_query_param = 'cursor'
# 按什么来排序
page.ordering = 'id'
ret_page = page.paginate_queryset(ret,request,view=self)
page_ser = TestSerializer(instance=ret_page,many=True)
# 使用get_paginated_response 可以避免页码被猜到
return page.get_paginated_response(page_ser.data)
posted on 2019-07-06 17:05 michael-chang 阅读(276) 评论(1) 编辑 收藏 举报