一 基于GenericAPIView完成接口
models.py
from django.db import models # Create your models here. class BaseModel(models.Model): create_time = models.DateTimeField(auto_now_add=True) last_updata_time = models.DateTimeField(auto_now=True) is_delete = models.BooleanField(default=False) class Meta: abstract = True class Book(BaseModel): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) authors = models.ManyToManyField(to='Author',db_constraint=False) publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False) def __str__(self): return self.name @property def publish_name(self): return self.publish.name def author_list(self): author_list = self.authors.all() return [{'name':author.name,'sex':author.get_sex_display()} for author in author_list] class Publish(BaseModel): name = models.CharField(max_length=32) addr=models.CharField(max_length=32) def __str__(self): return self.name class Author(BaseModel): name=models.CharField(max_length=32) sex=models.IntegerField(choices=((1,'男'),(2,'女'))) # 一对一关系,写在查询频率高的一方 #OneToOneField本质就是ForeignKey+unique,自己手写也可以 authordetail=models.OneToOneField(to='AuthorDetail',db_constraint=False,on_delete=models.CASCADE) def __str__(self): return self.name class AuthorDetail(BaseModel): mobile=models.CharField(max_length=11) 二、表断关联 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段) 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作) 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制 4、断关联 5、级联关系 作者没了,详情也没:on_delete=models.CASCADE 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
serializers.py
from rest_framework import serializers from api.models import Book class BookListSerializer(serializers.ListSerializer): def update(self, instance, validated_data): return [ self.child.update(instance[i],attrs) for i,attrs in enumerate(validated_data) ] class BookSerializers(serializers.ModelSerializer): class Meta: list_serializer_class = BookListSerializer model = Book fields = ('name','price','author_list','publish_name','publish','authors') extra_kwargs = { 'publish': {'write_only': True}, 'authors': {'write_only': True}, 'author_list':{'read_only': True}, 'publish_name':{'read_only': True}, } views.py from django.shortcuts import render from rest_framework.generics import GenericAPIView from api import models from until.serializers import BookSerializers from rest_framework.response import Response from until import pagination # Create your views here. class BookView(GenericAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializers def get(self,request,*args,**kwargs): if kwargs.get('pk',None): book_obj = self.get_object() book_ser = self.get_serializer(book_obj) else: book_list = self.get_queryset() # 配置分页 page_cursor = pagination.MyPageNumberPagination() book_list = page_cursor.paginate_queryset(book_list, request, view=self) book_ser = self.get_serializer(book_list, many=True) return Response(book_ser.data) def post(self,request,*args,**kwargs): if isinstance(request.data,dict): book_ser = self.get_serializer(data=request.data) book_ser.is_valid(raise_exception = True) book_ser.save() else: book_ser = self.get_serializer(data=request.data,many=True) book_ser.is_valid(raise_exception=True) book_ser.save() return Response(book_ser.data) def delete(self,request,*args,**kwargs): pk = kwargs.get('pk') pks=[] if pk: pks.append(pk) else: pks = request.data.get('pks') ret = models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True) if ret: return Response(data={'msg': '删除成功'}) else: return Response(data={'msg': '没有要删除的数据'}) def put(self,request,*args,**kwargs): if kwargs.get('pk',None): book_obj = self.get_object() book_ser = self.get_serializer(instance=book_obj,data=request.data,partial=True) book_ser.is_valid(raise_exception = True) book_ser.save() else: book_list = [] modify_data = [] for item in request.data: pk = item.pop('id') book = models.Book.objects.get(pk=pk) book_list.append(book) modify_data.append(item) book_ser = self.get_serializer(instance=book_list,data=modify_data,many=True,partial=True) book_ser.is_valid(raise_exception=True) book_ser.save() return Response(book_ser.data) urls.py urlpatterns = [ path('admin/', admin.site.urls), path('books/', views.BookView.as_view()), re_path('books/(?P<pk>d+)', views.BookView.as_view()), ]
pagination.py
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyPageNumberPagination(PageNumberPagination): #http://127.0.0.1:8000/api/books2/?aaa=1&size=6 page_size=3 #每页条数 # page_query_param='aaa' #查询第几页的key page_size_query_param='size' # 每一页显示的条数 max_page_size=5 # 每页最大显示条数 class MyLimitOffsetPagination(LimitOffsetPagination): page_size=3 limit_query_param = 'limit' # 往后拿几条 offset_query_param = 'offset' # 标杆 max_limit = 5 # 每页最大几条 class MyCursorPagination(CursorPagination): cursor_query_param = 'cursor' # 每一页查询的key page_size = 2 #每页显示的条数 ordering = '-id' #排序字段
二 分页器
上面代码中我们已经用了分页器,现在让我们总结下分页器的使用
1 内置三种分页方式
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
1.1 PageNumberPagination
前端访问网址形式:
GET http://127.0.0.1:8000/students/?page=4
可以在子类中定义的属性:
- page_size 每页数目
- page_query_param 前端发送的页数关键字名,默认为”page”
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量
1.2 LimitOffsetPagination
前端访问网址形式:
GET http://127.0.0.1/four/students/?limit=100&offset=400
可以在子类中定义的属性:
- default_limit 默认限制,默认值与
PAGE_SIZE
设置一直 - limit_query_param limit参数名,默认’limit’
- offset_query_param offset参数名,默认’offset’
- max_limit 最大limit限制,默认None
1.3 CursorPagination
前端访问网址形式:
GET http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
可以在子类中定义的属性:
- cursor_query_param:默认查询字段,不需要修改
- page_size:每页数目
- ordering:按什么排序,需要指定
1.4 三种分页器在不同视图函数中的使用
继承了APIView和GenericAPIView的视图函数
def get(self,request,*args,**kwargs): book_list=models.Book.objects.all() # 实例化得到一个分页器对象:上面代码把三个内置分页器都写出来了,想用哪个就实例化哪个,参数自己修改就行 page_cursor=MyPageNumberPagination() book_list=page_cursor.paginate_queryset(book_list,request,view=self) book_ser=BookModelSerializer(book_list,many=True) return Response(data=book_ser.data) # 继承GenericeAPIView也是这两句代码写在self.get_get_queryset()和book_ser = self.get_serializer(book_list, many=True)之间就行
继承ListAPIView等的视图函数
class BookView(ListAPIView): queryset = models.Book.objects.all() serializer_class = BookModelSerializer #配置分页 pagination_class = MyCursorPagination
1.5 全局和局部的使用
我们可以在配置文件中设置全局的分页方式,如:
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 # 每页数目 }
也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas
属性来指明。代码上面写了
注意:如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
2 总结
PageNumberPagination和LimitOffsetPagination这两个分页器是把所有数据进行检索,然后生成的,可以根据参数跳转或者是找到具体的一条数据。
CursorPagination是把所有数据进行排序显示,无法跳着显示数据,只能点上一页下一页,想找某条具体的数据只能一页一页的点,但是这个分页器在数据量大的时候速度快