PageNumberPagination、LimitOffsetPagination、CursorPagination

数据

from django.db import models


class User(models.Model):
    username = models.CharField(max_length=64, verbose_name='用户名')
    password = models.CharField(max_length=64, verbose_name='密码')

    # 用户类型
    user_type = models.IntegerField(choices=((1, '菜鸟用户'), (2, '普通用户'), (3, '超级用户')), verbose_name='用户级别')


# 一对一的关系,关联字段写好之后,要考虑谁拿谁的情况多,最好将用的多的放外键
class UserToken(models.Model):
    token = models.CharField(max_length=64, verbose_name='随机字符串')
    user = models.OneToOneField(to=User, on_delete=models.CASCADE)
    # 也等于
    # user = models.ForeignKey(to=User, unique=True, on_delete=models.CASCADE)


class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name='书名')
    price = models.IntegerField(verbose_name='书价')
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    users = models.ManyToManyField(to=User)

    def publish_detail(self):
        return {'name': self.publish.name, 'addr': self.publish.addr}

    def user_list(self):
        lst = []
        for user in self.users.all():
            lst.append({
                'username': user.username,
                'password': user.password,
                'user_type': user.get_user_type_display()
            })


class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name='出版社名称')
    addr = models.CharField(max_length=32, verbose_name='出版社地址')



路由

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter, SimpleRouter

from app01.views import BookView

router = SimpleRouter()
router.register('books', BookView, 'books')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls))
]

序列化类

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import User, UserToken, Book, Publish


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'


class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = '__all__'


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['title', 'price', 'publish', 'users', 'publish_detail', 'user_list']
        extra_kwargs = {
            'publish': {'write_only': True},
            'users': {'write_only': True},
        }

    publish_detail = serializers.DictField(read_only=True)
    user_list = serializers.ListField(read_only=True)

    def validate_users(self, value):
        if len(value) > 5:
            raise ValidationError('一本图书的作者最多5个')
        return value

    def validate(self, attrs):
        title = attrs.get('title')
        publish = attrs.get('publish')

        # 检查 title 和 publish 是否包含敏感信息
        sensitive_words = ['SB', 'DJB', 'CNM']
        for word in sensitive_words:
            if word in title:
                raise ValidationError('标题包含敏感信息')
            if word in publish:
                raise ValidationError('出版社名称包含敏感信息')

        return attrs

分页 page.py

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


# 继承PageNumberPagination分页
class CommonPageNumberPagination(PageNumberPagination):
    # 过滤形式
    # http://api.example.org/accounts/?page=4
    # http://api.example.org/accounts/?page=4&page_size=100

    # 需要重写几个类属性
    page_size = 3  # 每页显示2条
    page_query_param = 'page'  # 指定第几页的 key 值
    page_size_query_param = 'size'  # 指定每页显示多少条
    max_page_size = 5  # 每页最多显示5条


# 继承LimitOffsetPagination分页
class CommonLimitOffsetPagination(LimitOffsetPagination):
    # 过滤形式
    # http://api.example.org/accounts/?limit=3  从开始取3条
    # http://api.example.org/accounts/?offset=4&limit=5  从第4条开始取5条
    default_limit = 2  # 默认每页显示3条
    limit_query_param = 'limit'  # 每页显示多少条的查询条件
    offset_query_param = 'offset'
    max_limit = 5


# 继承CursorPagination分页
class CommonCursorPagination(CursorPagination):
    # 只能上一条和下一条,不能指定跳转到中间的某页----》效率高,大数据
    cursor_query_param = 'cursor'  # 查询条件,用不到,需要有
    page_size = 2  # 每页显示2条
    ordering = 'id'  # 按id排序

视图函数

PageNumberPagination

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from .models import Book
from .serializer import BookSerializer
from rest_framework.viewsets import ViewSetMixin


from .page import CommonPageNumberPagination


class BookView(ViewSetMixin, GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    pagination_class = CommonPageNumberPagination

    def list(self, request, *args, **kwargs):
        # 查询所有数据
        queryset = self.filter_queryset(self.get_queryset())
        # 分页处理
        page_list = self.paginate_queryset(queryset)

        if page_list:
            ser = self.get_serializer(page_list, many=True)
            return self.get_paginated_response(data=ser.data)

        ser = self.get_serializer(queryset, many=True)
        return Response(ser.data)

LimitOffsetPagination

from .page import CommonLimitOffsetPagination


class BookView(ViewSetMixin, GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CommonLimitOffsetPagination

    def list(self, request, *args, **kwargs):
        # 获取查询集
        queryset = self.filter_queryset(self.get_queryset())

        # 分页处理
        page_list = self.paginate_queryset(queryset)
        if page_list:
            serializer = self.get_serializer(page_list, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

CursorPagination

from .page import CommonCursorPagination


class BookView(ViewSetMixin, GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CommonCursorPagination

    def list(self, request, *args, **kwargs):
        # 获取查询集
        queryset = self.filter_queryset(self.get_queryset())

        # 分页处理
        page_list = self.paginate_queryset(queryset)
        if page_list is not None:
            serializer = self.get_serializer(page_list, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

报错

1.先写个函数
from rest_framework.views import exception_handler
from rest_framework.response import Response


def common_exception(exc, context):
    res = exception_handler(exc, context)
    if not res:
        return Response({'code': 999, 'msg': f'非drf错误,错误信息是:{str(exc)}'})
    return Response({'code': 666, 'msg': f'这是drf错误,错误信息是:{res.data.get("detail")}'})


2.在配置文件中配置:

REST_FRAMEWORK = {
    # 以后只要除了异常,都会走这个函数
    'EXCEPTION_HANDLER': 'app01.exceptions.common_exception',
}


你可能感兴趣的:(python01,django,django,restframework,分页)