如果查询参数错误,如何停止django REST框架以显示所有记录

时间:2014-11-28 05:36:01

标签: django django-rest-framework

我正在使用Django REST Framework,我正在使用过滤器来过滤查询集。

http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

像这样

http://example.com/api/products/4675/?category=clothing&max_price=10.00

但我已经看到,如果过滤器中存在错误或者查询参数不存在,那么它会显示所有非常糟糕的结果。

如果查询参数存在问题,我宁愿不想要结果,因为有时我不知道这是否有效

修改

这是我的代码

class userFilter(django_filters.FilterSet):
    strict = True

    class Meta:
        model = User
        fields = ('is_active', 'is_archived', 'age')

REST

class UserListCreateView(generics.ListCreateAPIView):
    queryset = User.objects.filter(is_archived=False)
    ordering_fields = ('is_active')
    filter_class = userFilter

这是REST设置

REST_FRAMEWORK = {
    'DEFAULT_MODEL_SERIALIZER_CLASS':
        'rest_framework.serializers.HyperlinkedModelSerializer',
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
        'rest_framework.filters.OrderingFilter',
    ),
    # 'PAGINATE_BY': 1,                 
    'PAGINATE_BY_PARAM': 'page_size',  
    'MAX_PAGINATE_BY': 100,             
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    )
}

5 个答案:

答案 0 :(得分:3)

如果您使用DjangoFilterBackend,请查看strict Non-Meta option

  

strict选项控制是否在返回时返回结果   用户为任何过滤器字段指定了无效值。通过   default,strict设置为True表示空查询集   如果任何字段包含无效值,则返回。你可以放松一下   通过将strict设置为False来有效地忽略一个行为   过滤字段,如果其值无效。

过滤器:

from django_filters.filterset import FilterSet

class UserFilter(FilterSet):
    strict = True

    class Meta:
        model = User
        fields = ['username']

设置:(假设您已安装django-filter

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}

现在,如果有人这样做:

http://api.example.com/users/?username=myuser&badfilter=1

...它将返回一个空列表,因为badfilter不存在。

由于FilterSet自动默认为strict=True,我觉得您没有利用DjangoFilterBackend

答案 1 :(得分:1)

明确的答案对我没有用。我通过重写" get"解决了这个问题。方法:

class UserListCreateView(generics.ListCreateAPIView):
    queryset = User.objects.filter(is_archived=False)
    ordering_fields = ('is_active')
    filter_class = userFilter

    @staticmethod
    def is_valid_query_params(query_params):
        # do validations here
        ...

    def get(self, request, *args, **kwargs):
        if not self.is_valid_query_params(request.query_params):
            return Response([])  # send empty response 
        return super(UserListCreateView, self).get(request, *args, **kwargs)

答案 2 :(得分:1)

您的具体问题源于您在GET查询中调用的参数未在UserFilter中定义。因此,DRF仅考虑以下参数:

fields = ('is_active', 'is_archived', 'age')

此外strict仅控制查询参数的不控制参数本身。例如

GET mydomain.com/resource_path?whatever=blabla

返回整个查询集,这在我看来是错误的,至少不符合REST。

我最后写了一个小方法来手动检查请求中传递的查询参数是否确实存在。

答案 3 :(得分:1)

我是通过在继承generics.ListAPIView的类中重载函数get_queryset()来实现的。您可以使用self.request.query_params检查params,并为任何情况编写自定义处理程序。

答案 4 :(得分:0)

According to the authorstrict仅过滤分配给查询参数的,而不过滤查询参数的 existence

否则,诸如分页之类的东西会添加自己的查询参数,这会破坏API。

您可以覆盖get_queryset()来验证查询键:

class List(generics.ListAPIView):       

    queryset = MyModel.objects.all()                                          
    serializer_class = MyModelSerializer                                       
    filter_fields = ('q1', 'q2',)
    # or filter_class

    def get_queryset(self):
        paging = set(['limit', 'offset'])
        qs = super(RestrictedQueryMixin, self).get_queryset()
        # Optional mutual exclusion check below...
        if hasattr(self, 'filter_fields') and hasattr(self, 'filter_class'):
            raise RuntimeError("%s has both filter_fields and filter_class" % self)
        if hasattr(self, 'filter_class'):
            filter_class = getattr(self, 'filter_class', None)
            filters = set(filter_class.get_filters().keys())
        elif hasattr(self, 'filter_fields'):
            filters = set(getattr(self, 'filter_fields', []))
        else:
            filters = set()
        for key in self.request.GET.keys():
            if key in paging:
                continue
            if key not in filters:
                return qs.none()
        return qs        

我把它变成了mixin。

或者,您可以加注rest_framework.exceptions.APIException。您也可以从self.paginator.get_schema_fields(self)

动态获取分页器字段