Skip to main content
 首页 » 编程设计

python之django-rest-framework- 使用 'or' 过滤来自一个 url 参数的多个值

2024年11月01日22tuyile006

我为我的 API 公开的模型准备了一个标记系统。这些模型看起来像这样:

class TaggableModel(models.Model): 
    name = models.CharField(max_length=255) 
    tags = models.ManyToManyField(Tag, related_name="taggable_models") 
 
class Tag(models.Model): 
    tag = models.CharField(max_length=32) 

然后我设置了一个序列化程序并查看如下所示:

class TaggableModelSerializer(serializers.ModelSerializer): 
    class Meta: 
        model = TaggableModel 
        fields = ('id', 'name', 'tags',) 
        read_only_fields = ('id',) 
 
class TaggableModelViewSet(viewsets.ModelViewSet): 
    queryset = TaggableModel.objects.all() 
    serializer_class = TaggableModelSerializer 
    permission_classes = (AllowAny,) 
    filter_backend = [DjangoFilterBackend] 
    filterset_fields = ['tags'] 

如果我想获取标签 ID 为 1、2 或 3 的所有 TaggableModels,我可以通过以下方式实现:

https://my-api-domain/api/taggable-models?tags=1&tags=2&tags=3

有没有一种方法可以在分隔符上进行拆分,这样我就可以将它们全部作为一个参数传递?例如:

https://my-api-domain/api/taggable-models?tags=1,2,3

看起来我可以编写自己的自定义 DjangoFilterBackend 过滤器,但我不确定从哪里开始。或者也许有更简单的方法来完成此操作?

请您参考如下方法:

当然,您可以通过具有特定字段“widget”的自定义过滤器集类来做到这一点(这就是它在 django-filters 中的调用方式)

这是您可以尝试的示例:

# filters.py 
 
from django_filters.rest_framework import FilterSet, filters 
from django_filters.widgets import CSVWidget 
 
from .your_models import Tag, TaggableModel 
 
class TaggableModelFilterSet(FilterSet): 
    tags = filters.ModelMultipleChoiceFilter( 
        queryset=Tag.objects.all(), widget=CSVWidget, 
        help_text=_("A list of ids, comma separated, identifying tags"), 
        method='filter_tags' 
    ) 
 
    class Meta: 
        model = TaggableModel 
        fields = ['tags'] 
 
    def filter_tags(self, queryset, name, value): 
        if value: 
            queryset = queryset.filter(tags__in=value) 
        return queryset 
# views.py 
 
class TaggableModelViewSet(viewsets.ModelViewSet): 
    queryset = TaggableModel.objects.all() 
    serializer_class = TaggableModelSerializer 
    permission_classes = (AllowAny,) 
    filter_backends = [DjangoFilterBackend] 
    filter_class = TaggableModelFilterSet