django_filters结合drf

时间:2023-02-14 19:02:24
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    description = models.TextField()
    release_date = models.DateField()
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)

django传统过滤查询集方式

Product.objects.filter(name__icontains='小明')
Product.objects.filter(release_date__gt=date(2023, 2, 12))
Product.objects.filter(price__gt=10)

直接使用

django可以直接使用获取queryset

queryset = ProductFilter(Product.objects.all()).queryset

搭配drf

drf当然搭配django-filters更加优雅。而不是在get_queryset方法中书写传统的查询方法。默认每个字段的值相等。更复杂的过滤需要定义FilterSet

import django_filters

class ProductFilter(django_filters.FilterSet):
    # 模糊搜索name字段
    name = django_filters.CharFilter(lookup_expr='contains')
    price_gt = django_filters.NumberFilter(lookup_expr='gte', field_name='price')

    class Meta:
        model = Product
        fields = ['price', 'release_date']

书写形式类似rest_framework序列化器。

核心参数

lookup_expr指代Django QuerySet语法

field_name筛选的模型字段和模型字段对应。

集成drf

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'django_filters',
]

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
      	# 全局配置
        'django_filters.rest_framework.DjangoFilterBackend',
        ...
    ),
}
# views
from rest_framework import serializers
from rest_framework.generics import GenericAPIView, ListAPIView
import django_filters


class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'


class ProductGenericAPIView(ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    # 使用 filterset_class 指定 FilterSet 默认只有相等或者前端书写类似 django查询表达式样式。前端是不能接受而且不易维    护
    filterset_class = ProductFilter
    # 另外,还可以指定filterset_fields指定查询的某些字段
    filterset_fields = ('name', 'price')

前端请求方式

xxx/?name=xxx&price=xxx
pip install django-filter

当然,以上放到一个py文件中是为了能够能够更快速得到结果。每个模块下,序列化器应放到serializers.py,过滤器放到filters.py下。