一、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)