首页 > 解决方案 > django-rest-framework 中字段的单独搜索过滤器

问题描述

Django-rest-framework 将有一个SearchFilter后端,允许对可搜索字段进行单个查询:

class OrganizationViewSet(viewsets.ModelViewSet):
    queryset = Organization.objects.all()
    serializer_class = OrganizationSerializer
    pagination_class = CustomPagination
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    filter_fields = ('sector', 'industry', 'marketplace')
    search_fields = ('symbol',)

这样,当我查询时,...?search=AMZ它只会返回symbol字段中具有非敏感匹配的记录。

如果我在元组中添加另一个元素search_fields,它将在两者中查找相同的搜索字符串。

有没有办法单独定义这些搜索字段,这将允许我执行以下操作:

?search_symbol=AMZ&search_name=Good以便它查找AMZsymbol字段中和good字段中具有的对象name

标签: pythondjangodjango-rest-framework

解决方案


要实现这一点,您将需要一个扩展rest_framework.filters.SearchFilter类的自定义过滤器后端。具体在rest_framework.filters.SearchFilter类中有一个方法get_search_terms

    def get_search_terms(self, request):
        """
        Search terms are set by a ?search=... query parameter,
        and may be comma and/or whitespace delimited.
        """
        params = request.query_params.get(self.search_param, '')
        return params.replace(',', ' ').split()

我们可以在我们自己的CustomSearchFilter类中重写这个方法来控制你如何在 url 中指定搜索词,例如:

class CustomSearchFilter(SearchFilter):
    search_field_prefix = "search_"

    def get_search_terms(self, request):
        # get search fields from the class
        search_fields = getattr(request.resolver_match.func.view_class, 'search_fields', list())

        params = []

        # iterate over each query paramater in the url
        for query_param in request.query_params:

            # check if query paramater is a search paramater
            if query_param.startswith(CustomSearchFilter.search_field_prefix):

                # extrapolate the field name while handling cases where <CustomSearchFilter.search_field_prefix> is in the field name
                field = CustomSearchFilter.search_field_prefix.join(
                    query_param.split(CustomSearchFilter.search_field_prefix)[1:]
                )

                # only apply search filter for fields that are in the views search_fields
                if field in search_fields:
                    params.append(request.query_params.get(query_param, ''))

        return params

现在在你的意见filters.SearchFilter中用你的新替换。CustomSearchFilterfilter_backends

希望这会有所帮助,我在没有自己测试代码的情况下编写了这个,所以让我知道你是怎么做的!


推荐阅读