为了账号安全,请及时绑定邮箱和手机立即绑定

django-rest-framework- 使用“或”过滤来自一个 url 参数的多个值

django-rest-framework- 使用“或”过滤来自一个 url 参数的多个值

人到中年有点甜 2022-05-24 12:53:47
我为我的 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']如果我想获取所有TaggableModels标签 ID 为 1、2 或 3 的内容,可以通过以下方式进行: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 过滤器,但我有点不确定从哪里开始。或者也许有更简单的方法来实现这一点?
查看完整描述

2 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

当然,您可以通过使用具有特定字段“小部件”的自定义过滤器集类来做到这一点(这就是它在 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


查看完整回答
反对 回复 2022-05-24
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

django-filter使用package有一种更简单的方法来实现这一点。django-filter在文档的深处,它提到您可以使用“映射到查找列表的字段名称字典”。


您的代码将像这样更新:


# views.py


from django_filters.rest_framework import DjangoFilterBackend


class TaggableModelViewSet(viewsets.ModelViewSet):

    queryset = TaggableModel.objects.all()

    serializer_class = TaggableModelSerializer

    permission_classes = (AllowAny,)

    filter_backend = [DjangoFilterBackend]

    filterset_fields = {

        'tags': ["in", "exact"] # note the 'in' field

    }

现在在 URL 中,您将__in在提供参数列表之前添加到过滤器中,它会按预期工作:


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

关于哪些查找过滤器可用的django-filter文档非常差,但是在Django 文档本身in中提到了查找过滤器。


查看完整回答
反对 回复 2022-05-24
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号