将属性作为API中的过滤器字段

时间:2018-04-28 16:07:22

标签: django django-rest-framework

我有这个型号:

class Auction(models.Model):
    start_price = models.IntegerField()
    price_step = models.IntegerField()
    finish_time = models.DateTimeField()

    @property
    def is_active(self):
        return self.finish_time > timezone.now()

我的序列化程序类中也有这个:

class AuctionSerializer(serializers.ModelSerializer):
    is_active = serializers.ReadOnlyField()

    class Meta:
        model = Auction
        fields = '__all__'

这在我的观点课程中:

class AuctionViewSet(ModelViewSet):
    queryset = Auction.objects.all()
    serializer_class = AuctionSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('is_active',)

但是它会引发Meta.fields'包含未在此FilterSet上定义的字段:is_active"。我可以将它用作序列化器字段,但我无法通过此字段进行过滤。如何通过模型属性正确实现过滤,而不仅仅是模型字段?

1 个答案:

答案 0 :(得分:1)

AFAIK,django-filter不支持按属性过滤。

这样做的一种方法是按原样公开模型;并期望FE相应地过滤。

例如:过滤器URI可能看起来像http://localhost:8000/api/auctions/?finish_time__gte=2018-04-28T00:00:00

但是,如果你想要一个明确的声明;您可以覆盖get_queryset中的ModelViewSet方法,如下所示:

class AuctionViewSet(ModelViewSet):
    queryset = Auction.objects.all()
    serializer_class = AuctionSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('is_active',)

    def filter_active(qs):
        return qs.filter(finish_time__gte=timezone.now())

    def filter_inactive(qs):
        return qs.filter(finish_time__lt=timezone.now())

    def get_queryset():
        qs = super(AuctionViewSet, self).get_queryset()
        is_active = self.request.GET.get('is_active', None)  # This will be a string
        if is_active is None:
            pass
        elif is_active == 'true':
            qs = self.filter_active(qs)
        elif is_active == 'false':
            qs = self.filter_inactive(qs)
        else:
            pass  # Some other value
        return qs

参考: https://django-filter.readthedocs.io/en/master/guide/rest_framework.html#schema-generation-with-core-api