【问题标题】:Create custom filter创建自定义过滤器
【发布时间】:2019-04-04 08:23:47
【问题描述】:

目前我的看法如下:

from rest_framework.permissions import AllowAny
from dynamic_rest.viewsets import DynamicModelViewSet
from django_filters.rest_framework import DjangoFilterBackend

from .models import Purchase
from .serializers import PurchaseSerializer


class PurchasesViewSet(DynamicModelViewSet):
    queryset = Purchase.objects.all()
    serializer_class = PurchaseSerializer
    permission_classes = (AllowAny,)
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('name', 'color')

这让我可以准确地过滤namecolor

我的数据有一个date 字段(DateField 类型)。我想按“季度”创建一个自定义过滤器,以便这种请求:

/purchases/?quarter=2018Q1

提供指定季度中带有date 字段的对象列表。请注意,quarter 不是模型字段。

创建这样一个自定义过滤器的方法是什么?

【问题讨论】:

  • 一种方法是创建一个代理模型,其字段包含来自DateField 的季度信息,然后使用该字段进行过滤。

标签: django django-rest-framework django-filter


【解决方案1】:

首先,您必须创建 自定义过滤器 以及 过滤器类

import django_filters
from rest_framework.exceptions import ValidationError


class QuarterFilter(django_filters.Filter): # Custom Filter
    def get_quarter_range(self, quarter):
        if quarter == 1:
            return [1, 3]
        elif quarter == 2:
            return [4, 6]
        elif quarter == 3:
            return [7, 9]
        elif quarter == 4:
            return [10, 12]
        else:
            raise ValidationError("quarter value must be range from 1-4")

    def filter(self, qs, value):
        """
        create your custom filtering logi here
        """
        # here the "value" will be the value parsed from URL params, ie "2018Q1"
        try:
            year, quarter = value.split("Q") # spliting the input to get year and quarter value
            qs = qs.filter(date__year=year)

            qs = qs.filter(date__month__range=self.get_quarter_range(quarter))
            return qs
        except:
            return qs


class PurchaseFilter(django_filters.FilterSet): # Custom Filter Class
    quarter = QuarterFilter()

    class Meta:
        model = Purchase
        fields = ['name', 'color', 'quarter']



然后,在您的视图类中使用filterset_class 属性提及它。那么你的观点就像,

class PurchasesViewSet(DynamicModelViewSet):
    queryset = Purchase.objects.all()
    serializer_class = PurchaseSerializer
    permission_classes = (AllowAny,)
    filter_backends = (DjangoFilterBackend,)
    # filter_fields = ('name', 'color') ---- Remove this line of code
    filterset_class = PurchaseFilter



注意
我不确定这条线,

qs = qs.filter(date__month__range=self.get_quarter_range(quarter))

但是,在这种特殊情况下,您需要这样做过滤。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您可以在 filter_class 中创建自定义过滤器

    from rest_framework import filters
    
    class CustomFilter(django_filters.rest_framework.FilterSet):
        class Meta:
            model = Purchase
            fields = ['name', 'color', 'quarter']
        quarter = QuarterFilter(name="quarter")
    
    class QuarterFilter(django_filters.Filter):
        def filter(self, qs, value):
            # create custom in this with value
            return qs.filter(name=value)
    
    class PurchasesViewSet(DynamicModelViewSet):
        queryset = Purchase.objects.all()
        serializer_class = PurchaseSerializer
        permission_classes = (AllowAny,)
        filter_backends = (DjangoFilterBackend,)
        filter_class = CustomFilter
    

    【讨论】:

      猜你喜欢
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多