分页器

一、图书的创建

1、models

from django.db import models

# Create your models here.
from django.contrib.auth.models import AbstractUser


class BaseModel(models.Model):
    # is_delete = models.BooleanField(choices=((0, '未删除'), (1, '删除')), default=0)
    is_delete = models.BooleanField(default=False)
    create_time = models.DateTimeField(auto_now_add=True)
    last_update_time = models.DateTimeField(auto_now=True)

    class Meta:
        # 可以修改表名,可以建联合索引
        '''
        单个字段可以建唯一键索引
        多个字段:联合索引,联合唯一
        '''
        abstract = True  # 抽象表,不在数据库建立表


class Book(BaseModel):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    # db_constraint=False:逻辑上关联上了,实际上没有外键关联,增删不会受到外键影响,orm查询也不影响
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, db_constraint=False)
    author = models.ManyToManyField(to='Author', db_constraint=False)

    class Meta:
        verbose_name_plural = '图书表'

    def __str__(self):
        return self.name
    
    @property  # 把方法包装成数据属性
    def publish_detail(self):
        return {'name': self.publish.name, 'addr': self.publish.addr}

    @property  # 把方法包装成数据属性
    def author_detail(self):
        # 获取所有作者
        author_list = self.author.all()
        author_list_dict = []
        for author in author_list:
            author_list_dict.append({'name': author.name, 'sex': author.get_sex_display()})
        return author_list_dict


class Publish(BaseModel):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = '出版社表'

    def __str__(self):
        return self.name


class Author(BaseModel):
    name = models.CharField(max_length=32)
    sex = models.IntegerField(choices=((1, '男'), (2, '女')))
    authordetail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE, db_constraint=False)

    class Meta:
        verbose_name_plural = '作者表'

    def __str__(self):
        return self.name


class AuthorDetail(BaseModel):
    mobile = models.CharField(max_length=22, verbose_name='手机号')

    class Meta:
        verbose_name_plural = '作者详细表'

    def __str__(self):
        return self.mobile


# 二、表断关联
# 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

2、admin.py

from django.contrib import admin
from api import models

admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)

2.1、创建超级用户

createsuperuser

3、serializer.py

from rest_framework import serializers
from api.models import Book


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'price', 'publish', 'author', 'publish_detail', 'author_detail']
        extra_kwargs = {
            'publish': {'write_only': True},
            'author': {'write_only': True},
            'publish_detail': {'read_only': True},
            'author_detail': {'read_only': True}
        }

4、views.py(批量增、改、删)

from django.shortcuts import render
from rest_framework.views import APIView
from api.models import Book
from api.serializer import BookModelSerializer
from rest_framework.response import Response


class BookView(APIView):
    def get(self, request, *args, **kwargs):
        # 查询单条和查询所有,合在一起
        book_list = Book.objects.all().filter(is_delete=False)
        ser = BookModelSerializer(instance=book_list, many=True)
        return Response(data=ser.data)
    
    def post(self, request, *args, **kwargs):
        # 增加单条数据
        if isinstance(request.data, dict):  # isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
            ser = BookModelSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return Response(data=ser.data)
        elif isinstance(request.data, list):
            # 增加多条数据
            ser = BookModelSerializer(data=request.data, many=True)  # 加上many增加多条
            ser.is_valid(raise_exception=True)
            ser.save()  # 调用的是ListSerializer方法
            return Response(data=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:受影响的行数
        ret = Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
        if ret:
            return Response(data={'msg': '删除成功'})
        else:
            return Response(data={'msg': '没有要删除的数据'})

5、路由分发urls

# 项目
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    # 路由分发
    path('api/', include('api.urls')),
]

# app
from django.urls import path
from api import views
urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookView.as_view()),
]

二、分页器Pagination

1、基本使用

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 2  # 每页数目
}

1.1、views.py

# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = PageNumberPagination
    
# 请求方式:http://127.0.0.1:8000/api/books2/page=3

2.1、通过自定义类分页

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。

# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


# 自定义类
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3  # 每页条数
    page_size_query_param = 'page_size'  # 每一页显示的条数
    max_page_size = 100   # 每页最大显示条数
    page_query_param = 'aaa'  # 查询第几页key


class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MyPageNumberPagination  # 自定义类
    
# 请求方式:http://127.0.0.1:8000/api/books2/?aaa=2&page_size=3

三、可选分页器

1、PageNumberPagination

前端访问网址形式:

GET http://127.0.0.1:8000/api/books2/?aaa=2&page_size=3

可以在子类中定义的属性:

  • page_size 每页数目
  • page_query_param 前端发送的页数关键字名,默认为”page”
  • page_size_query_param 前端发送的每页数目关键字名,默认为None
  • max_page_size 前端最多能设置的每页数量
# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

一、添加配置文件分页
class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = PageNumberPagination  # 自定义类


二、自定义类分页
# 自定义类
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3  # 每页条数
    page_size_query_param = 'page_size'  # 每一页显示的条数
    max_page_size = 100   # 每页最大显示条数
    page_query_param = 'aaa'  # 查询第几页key


class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MyPageNumberPagination  # 自定义类
    
# 请求方式:http://127.0.0.1:8000/api/books2/?aaa=2&page_size=3

2、LimitOffsetPagination

前端访问网址形式:

GET http://127.0.0.1:8000/api/books2/?limit=3&offset=1

可以在子类中定义的属性:

  • default_limit 默认限制,默认值与PAGE_SIZE设置一直
  • limit_query_param limit参数名,默认’limit’
  • offset_query_param offset参数名,默认’offset’
  • max_limit 最大limit限制,默认None
# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
一、添加配置文件分页
class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = LimitOffsetPagination  #  自定义类


二、自定义类分页
# 自定义类
class MyCursorPagination(CursorPagination):
    default_limit = 3  # 每页条数
    limit_query_param = 'limit'  # 向后展示几条
    offset_query_param = 'offset'  # 标杆
    max_limit = None  # 每页最大展示几条


class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MyCursorPagination  #  自定义类

3、CursorPagination

前端访问网址形式:

GET http://127.0.0.1/api/books2/?cursor=cD0xNQ%3D%3D

可以在子类中定义的属性:

  • cursor_query_param:默认查询字段,不需要修改
  • page_size:每页数目
  • ordering:按什么排序,需要指
# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


# 自定义类
class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 每一页查询的key
    page_size = 2  # 显示每页的条数
    ordering = '-created'  # 排序字段


class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MyCursorPagination

3.1、使用APIView实现分页器

# 只有查所有才需要分页
from rest_framework.generics import ListAPIView
# 内置三种分页方式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


# 自定义类
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3
    page_size_query_param = 'page_size'
    # max_page_size = 10000
    page_query_param = 'aaa'


# 使用APIView分页
class Book2View(APIView):
    def get(self, request, *args, **kwargs):
        # 获取所有数据
        book_list = Book.objects.all()
        # 创建分页对象
        page = MyPageNumberPagination()
        # 在数据库中获取分页的数据
        book_list = page.paginate_queryset(book_list, request, view=self)
        # 下一页和上一页
        next_url = page.get_next_link()
        pr_url = page.get_previous_link()
        # 对分页进行序列化
        ser = BookModelSerializer(book_list, many=True)
        return Response(data=ser.data)
posted @ 2022-02-08 15:56  迷恋~以成伤  阅读(144)  评论(0)    收藏  举报