django-filter詳解
過濾元件django-filter
官方文件:https://django-filter.readthedocs.io/en/main/
1 安裝
pip install django-filter
在django配置檔案中註冊app
INSTALLED_APPS = [
...
'django_filters', # 需要註冊應用,
]
環境需求:
- Python: 3.6, 3.7, 3.8
- Django: 2.2, 3.1, 3.2
- DRF: 3.10+
2 使用
給出一個模型表:
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)
模型表有很多欄位,我們想按照價格和日期排序,可以這樣做
import django_filters # 匯入模組
class ProductFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='iexact')
class Meta:
model = Product
fields = ['price', 'release_date']
django-filter支援跨表操作,也可以使用雙下劃線查詢,這樣會使過濾類顯得很冗長,但是保持了最大的自定義程度:
class ProductFilter(django_filters.FilterSet): price = django_filters.NumberFilter() price__gt = django_filters.NumberFilter(field_name='price', lookup_expr='gt') price__lt = django_filters.NumberFilter(field_name='price', lookup_expr='lt') release_year = django_filters.NumberFilter(field_name='release_date', lookup_expr='year') release_year__gt = django_filters.NumberFilter(field_name='release_date', lookup_expr='year__gt') release_year__lt = django_filters.NumberFilter(field_name='release_date', lookup_expr='year__lt') manufacturer__name = django_filters.CharFilter(lookup_expr='icontains') class Meta: model = Product fields = ['price', 'release_date', 'manufacturer']
過濾器有兩個主要引數:
- field_name:欄位名稱,你可以使用django中的雙下劃線查詢語法來使用
- lookup_expr:過濾時的過濾條件,支援雙下劃線語法
有關雙下劃線查詢,詳見這裡
欄位field_name和lookup_expr一起表示一個完整的Django查詢表示式。比如price__gt = django_filters.NumberFilter(field_name='price', lookup_expr='gt')
定義之後,瀏覽器get請求攜帶引數price__gt=10
,就會根據price
欄位過濾出符合條件價格大於10
的資料。
在Meta類中,model指定要過濾的模型表,fields指定通過哪些欄位來過濾。此外,可以使用字典為每個欄位指定多個查詢表示式:
import django_filters
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = {
'price': ['lt', 'gt'],
'release_date': ['exact', 'year__gt'],
}
如果包含外來鍵欄位,同樣可以使用雙下劃線語法:
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = ['manufacturer__country']
3 drf中使用
在drf中使用過濾:
from django_filters import rest_framework as filters
# 匯入並繼承FilterSet類
class ProductFilter(filters.FilterSet):
...
你的檢視類還需要將DjangoFilterBackend新增到filter_backend中(區域性配置)
from django_filters import rest_framework as filters
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,) # 配置filter_backends
filterset_fields = ('category', 'in_stock')
全域性配置:
REST_FRAMEWORK = { # 全域性配置
...
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
要使用FilterSet過濾,需要將其新增到檢視類的filterset_class引數中。
from rest_framework import generics
from django_filters import rest_framework as filters
from myapp import Product
# 定義過濾類
class ProductFilter(filters.FilterSet):
min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')
class Meta:
model = Product
fields = ['category', 'in_stock'] # 在Meta中指定過濾哪些欄位
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ProductFilter # 在filterset_class中,指定要使用的過濾類
由於支援雙下劃線語法,就可以在過濾類中建立區間過濾。比如ProductFilter中可以定義min_price和max_price,前端傳入最小价格和最大價格就可以過濾出相應欄位。
本文來自部落格園,作者:yyyz,轉載請註明原文連結:https://www.cnblogs.com/yyyzyyyz/p/15533452.html