django使用DRF进行分页,并进行过滤_django

相关环境安装:

djangorestframework

1. django使用DRF进行分页

drf框架中以及集成了相关的分页类,可以根据自己的需求添加相关的返回值。

相关后端实现代码部分

from rest_framework.pagination import PageNumberPagination

#自定义自己的分页类
class MyPagination(PageNumberPagination):
    page_size = 15    #每一页显示的数量
    max_page_size = 50
    page_query_param = 'page' #传入的parameter
    adjacent_pages = 5 #页面前后实现的页码数量
    
    def get_paginated_response(self,data):#重写PageNumberPagination下的get_paginated_response方法
        response = super().get_paginated_response(data)
        current_page = self.page.number
        total_page = self.page.pagintor.num_pages
        start_page = max(current_page - self.adjacent_pages, 1)
        end_page = min(current_page + self.adjacent_pages, total_page)
        response.data['displayed_pages'] = list(range(start_page, end_page + 1))
        response.data['current_page'] = current_page
        response.data['total_page'] = total_page

相关前端代码部分(jquery)

function updatePageination(displayed_pages,type="",content=""){
                           $("#pagination").empty()
                          // 遍历 displayed_pages 数组
                            displayed_pages.forEach(function(page) {
                                // 为每个页码创建一个 li 元素
                                var li = $("<li></li>");

                                // 检查当前页码是否是活动的页码
                                if (page === currentPage) {
                                    // 如果是活动的页码,添加一个 active 类
                                    li.addClass("active");
                                    // 链接到 #,因为活动页码通常不需要导航
                                    li.append($("<a></a>").attr("href", "#").text(page));
                                } else {
                                    // 如果不是活动的页码,创建一个链接到相应页码的 URL
                                    {#li.append($("<a></a>").attr("href", "{% url 'background:crime_content' %}?page=" + page).text(page));#}
                                    var a = $("<a></a>").text(page).attr("href","#").data({page:page,type:type,content:content});
                                    a.click(function(event){
                                        event.preventDefault();
                                        getData($(this).data("page"),$(this).data("type"),$(this).data("content"));
                                    })
                                    li.append(a);
                                }


                                // 将 li 元素添加到 pagination 列表中
                                $("#pagination").append(li);
                            });
                       }

DRF对针对请求条件对相关数据进行过滤操作

准备model相关数据库类方法

class admin_user_info(models.Model):
    id = models.AutoField(primary_key=True, null=False, blank=False)
    username = models.CharField(max_length=20, null=False, blank=False)
    password = models.CharField(max_length=20, null=False, blank=False)
    email = models.CharField(max_length=20, null=True, blank=True)
    telephone = models.CharField(max_length=14, null=True, blank=True)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = 'admin_user_info'

class crime_type(models.Model):
    id = models.AutoField(primary_key=True, null=False, blank=False)
    type_name = models.CharField(max_length=20, null=False, blank=False)
    type_by = models.ForeignKey(admin_user_info, on_delete=models.CASCADE, null=False, blank=False,related_name="relate_type")
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = 'crime_type'

这里准备了用户信息库和犯罪类型库,其中crime_typetype_by是引用的admin_user_info做外键

准备serializer相关类

  • 正常进行序列化操作,以及添加自己明确的相关字段
from rest_framework import serializers
from models import admin_user_info, crime_type

class admin_user_info_serializer(serializer.ModelSerializer):
    class Meta:
        model = admin_user_info
        fields = "__all__"
class crime_type_serializer(serializer.ModelSerializer):
    type_by = serializer.PrimaryKeyRelatedField(queryset=admin_user_info.objects.all()) #该字段必须与crime_type类外键字段一致
    crime_create_by = serializer.StringRelatedField(source="type_by.username",read_only=True) #source 之后是type_by指定数据,在返回的结果中就会存在crime_create_by这个字段
    class Meta:
        model = crime_type
        fields = "__all__"
  • 反向关联,利用related_name,在使用source的时候使用relateName_set,在关联名称之后加入_set
class Owner(models.Model):
    name = models.CharField(max_length=200)
class Pet(models.Model):
    owner = models.ForeignKey(Owner, related_name='pets', on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
#--------------------创建serializer-------------------------------
class PetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pet
        fields = ("id", "name")

class OwnerNewSerializer(serializers.ModelSerializer):
    pets = PetSerializer(many=True, source='pet_set')
    class Meta:
        model = Owner
        fields = ('id', 'name', 'pets')

在views.py中编写相关视图类(用于过滤)

from rest_framework.generics import GenericAPIView

class crime_content_view(GenericAPIView):
    queryset = crime_content.objects.all()
    serializer_class = crime_content_serializer
    pagination_class = MyPagination

    def get(self, request):
        query_params = request.query_params
        queryset = self.filter_queryset(self.get_queryset())
        content = query_params.get("content","")
        type = query_params.get("type","")
        if type != "" and content != "":
            queryset = queryset.filter(type=crime_type.objects.get(id=type), content__contains=content)
            print("type and content")
            print(len(queryset))
        elif content != "":
            queryset = queryset.filter(content__contains=content)
            print("content")
            print(len(queryset))
        elif type != "":
            queryset = queryset.filter(type=type)
            print("type")
            print(len(queryset))
        else:
            queryset = queryset.all()

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            # print(serializer)
            # return JsonResponse({"data":serializer,"status":200})
            return self.get_paginated_response(serializer.data)
        serializer = self.serializer_class(instance=self.queryset, many=True)
        return JsonResponse({"data": serializer.data, "status": 200})

    def post(self, request):

        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({"data": serializer.data, "status": 200})
        else:
            return JsonResponse({"data": serializer.errors, "status": 400})

    def put(self,request):
        id = request.data.get("id")
        instance = crime_content.objects.get(id=id)
        serializer = crime_content_serializer(instance=instance,data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({"data": serializer.data, "status": 200})
        else:
            return JsonResponse({"data": serializer.errors, "status": 400})

在不同的请求方法中,request获取数据的方式也不一样

get: reqeust.query_params

post:request.data

为了方式没有获取到值,可以使用.get("keyword","")的方式获取

过滤操作

class crime_content_view(GenericAPIView):
    queryset = crime_content.objects.all()
    serializer_class = crime_content_serializer
	def get(self,request):
        queryset = self.filter_queryset(self.get_queryset)
        queryset = queryset.filter(name__icontains="nuocheng")
        serializer = self.get_serializer(queryset)
        return Response(serializer.data)