django-filter 可以用来过滤查询. 跟 Django REST framework 很配.
使用
1 2 3 4 5 6 7 8 9
| from django.db import models
class Product(models.Model): name = models.CharField(max_length=255) price = models.DecimalField() description = models.TextField() release_date = models.DateField() manufacturer = models.ForeignKey(Manufacturer)
|
1 2 3 4 5 6 7
| import django_filters
class ProductFilter(django_filters.FilterSet): class Meta: model = Product fields = ['price', 'release_date']
|
指定字段, 排除字段
1 2 3 4 5
| class UserFilter(django_filters.FilterSet): class Meta: model = User fields = ['username', 'last_login']
|
1 2 3 4 5
| class UserFilter(django_filters.FilterSet): class Meta: model = User exclude = ['username', 'last_login']
|
过滤大于和小于或者包含等于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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') price__lte = django_filters.NumberFilter(field_name='price', lookup_expr='lte')
class Meta: model = Product
class ProductFilter(django_filters.FilterSet): class Meta: model = Product fields = { 'price': ['lt', 'gt'], 'release_date': ['exact', 'year__gt'], }
|
过滤范围
一般是名字里面包含 Range
, 例如 RangeFilter
, NumericRangeFilter
, DateRangeFilter
, DateFromToRangeFilter
, 查询时 url
为 /?date_after=2016-01-01&date_before=2016-02-01
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Comment(models.Model): date = models.DateField() time = models.TimeField()
class F(FilterSet): date = DateFromToRangeFilter()
class Meta: model = Comment fields = ['date']
f = F({'date_after': '2016-01-01', 'date_before': '2016-02-01'})
f = F({'date_after': '2016-01-01'})
f = F({'date_before': '2016-02-01'})
|
自定义 method
自定义搜索多个字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class F(django_filters.FilterSet): username = CharFilter(method='my_custom_filter')
class Meta: model = User fields = ['username']
def my_custom_filter(self, queryset, name, value): return queryset.filter(**{ name: value, })
from django.utils import timezone from datetime import timedelta ...
class DataModel(models.Model): time_stamp = models.DateTimeField()
class DataFilter(django_filters.FilterSet): hours = django_filters.NumberFilter( field_name='time_stamp', method='get_past_n_hours', label="Past n hours")
def get_past_n_hours(self, queryset, field_name, value): time_threshold = timezone.now() - timedelta(hours=int(value)) return queryset.filter(time_stamp__gte=time_threshold)
class Meta: model = DataModel fields = ('hours',)
|
1 2 3 4 5 6 7 8 9 10
| class ClassSellInfoFilter(filters_rest.FilterSet): fuzzy_search = filters_rest.CharFilter(method='search_title_or_class_tag')
def search_title_or_class_tag(self, queryset, name, value): return queryset.filter(Q(class_sell_title__icontains=value) | Q(class_name__class_tag__icontains=value))
class Meta: model = ClassSellInfo fields = ['fuzzy_search']
|
参考链接