Swagger UI 以“true/false”形式提交布尔参数,而 django 过滤器布尔字段需要 True/False(大写)。因此,当我通过 swagger 查询时,字段 is_published 不起作用。
{{api_url}}/api/v1/games/?limit=10&offset=0&is_published=true
{{api_url}}/api/v1/games/?limit=10&offset=0&is_published=false
过滤字段定义为
is_published = BooleanFilter(name='versions__is_published')
完整定义
class GameFilter(FilterSet):
"""Custom filter for ``GameViewSet``.
Defines custom filter for ``genres`` field (based on TaggableManager).
"""
is_published = BooleanFilter(name='versions__is_published')
class Meta:
model = Game
fields = {
'platforms': ['exact'],
'ages': ['exact'],
'developers': ['exact'],
'genres': ['exact'],
'created': ['gt', 'lt']
}
方法的 Swagger 定义
get:
summary: Get list of games
operationId: getGamesList
parameters:
- $ref: '../../parameters.yaml#/Offset'
- $ref: '../../parameters.yaml#/Limit'
- $ref: '../../parameters.yaml#/PlatformsFilter'
- $ref: '../../parameters.yaml#/DevelopersFilter'
- $ref: '../../parameters.yaml#/GenresFilter'
- $ref: '../../parameters.yaml#/AgesFilter'
- $ref: '../../parameters.yaml#/SearchFilter'
- $ref: '../../parameters.yaml#/Order'
- name: is_published
in: query
type: boolean
required: false
default: true
解决方案:
基础 django_filters.FilterSet 旨在与普通 Django 视图一起使用。如果您使用 DRF 创建 API,则应该使用 django_filters.rest_framework.FilterSet,因为它使用一组略有不同的过滤器,更适合在 API 中使用。在这种情况下,BooleanFilter 接受小写 true/false 值。
调整导入后:
from django_filters import ModelMultipleChoiceFilter
from django_filters.rest_framework import BooleanFilter, FilterSet
DRF 中 BooleanFilter 的问题在于它利用了模型过滤器 - 它依赖于类似 python 的值(True 或 False,大写 T。)
为了使其更加灵活,我通常创建自己的 BooleanFilter 版本,该版本更通用:
from django_filters.rest_framework import *
from django_filters.rest_framework import (BooleanFilter as OrigBooleanFilter)
class BooleanFilter(OrigBooleanFilter):
def filter(self, qs, value):
if value:
if value.lower() in ('true', 't', 'y', 'yes', '1'):
value = True
else:
value = False
return super().filter(qs, value)
然后导入此模块而不是 django_filters.rest_framework,这可以让您为自己的副本定义其他过滤器(和增强功能)。
我通常还会创建特殊的过滤器类来: