在django-rest-framework的过滤器中使用自定义方法

时间:2014-06-25 17:24:03

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

我想在REST API中过滤查询参数 - see django docs on this。 但是,我希望过滤的一个参数只能通过模型​​@property

获得

示例models.py:

class Listing(models.Model):
    product = models.OneToOneField(Product, related_name='listing')
    ...
    @property
    def category(self):
        return self.product.assets[0].category.name

以下是符合django-filter docs

的清单API的设置
    class ListingFilter(django_filters.FilterSet):
        product = django_filters.CharFilter(name='product__name')
        category = django_filters.CharFilter(name='category') #DOES NOT WORK!!

        class Meta:
            model = Listing
            fields = ['product','category']

    class ListingList(generics.ListCreateAPIView):
        queryset = Listing.objects.all()
        serializer_class = ListingSerializer
        filter_class = ListingFilter

如何通过listing.category进行适当的过滤?它不能直接在列表模型中使用。

2 个答案:

答案 0 :(得分:13)

使用'action'参数指定自定义方法 - see django-filter docs

首先使用category参数的值定义一个过滤查询集的方法:

    def filter_category(queryset, value):
        if not value:
            return queryset

        queryset = ...custom filtering on queryset using 'value'...
        return queryset

列表过滤器应如下所示:

    class ListingFilter(django_filters.FilterSet):
        ...
        category = django_filters.CharFilter(action=filter_category)
        ...

答案 1 :(得分:-2)

为了数据库速度,您只需将类别添加到商家信息模型

即可
class Listing(models.Model):
    product = models.OneToOneField(Product, related_name='listing')
    category = models.ForeignKey(Category)

然后使用post_save signal保持字段更新

from django.dispatch import receiver
from django.db.models.signals import post_save

@receiver(post_save, sender=Product)
def updateCategory(sender, instance, created, update_fields, **kwargs):
    product = instance
    product.listing.category = product.assets[0].category.name
    product.listing.save()

然后按照其他任何字段过滤它的名称:

class ListingFilter(django_filters.FilterSet):
    ...
    category = django_filters.CharFilter(name='category__name')
    ...