我正在使用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',
)
}
答案 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 author,strict
仅过滤分配给查询参数的值,而不过滤查询参数的 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)