zoukankan      html  css  js  c++  java
  • drf-books系列接口作业和分页器

    一 基于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是把所有数据进行排序显示,无法跳着显示数据,只能点上一页下一页,想找某条具体的数据只能一页一页的点,但是这个分页器在数据量大的时候速度快

     

  • 相关阅读:
    uva694 The Collatz Sequence
    WindowsPhone7开发简单豆瓣网应用程序之主页面功能实现
    使用codeplex管理WP7项目开发版本
    WindowsPhone7开发简单豆瓣网应用程序之界面设计
    WindowsPhone操作SkyDrive之获取共享文件
    Windows Phone7监测网络接口及状态变化
    《设计模式》杂记之里氏替换原则
    Silverlight杂记之HTTP通信WebClient介绍
    WindowsPhone获取是否进行拨电话信息[使用PhoneCallTask]
    《设计模式》杂记之单一职责原则
  • 原文地址:https://www.cnblogs.com/bk134/p/13306402.html
Copyright © 2011-2022 走看看