如何在DRF序列化器中解析字符串列表查询参数?

4
我将创建一个REST API来处理用户请求,其形式如下:
localhost:8000/search/?categories=<category1>,<category2>&parts=<id1>,<id2>

在解析器中,逗号,被认为是定界符。

我的视图处理请求并将查询参数传递给序列化程序,但我无法将原始字符串解析为字符串列表。

到目前为止,我的尝试:

class StringListField(serializers.ListField):
    child = serializers.CharField()

class LookupPartsSerializer(serializers.Serializer):
    categories = StringListField()
    parts = StringListField()

class LookupParts(APIView):

    def get(self, request, format=None):
        serializer = LookupPartsSerializer(data=request.query_params)
        serializer.is_valid()
        return Response(serializer.validated_data)

My desired output is like:

{
    "categories": [
        "<category1>",
        "<category2>"
    ],
    "parts": [
        "<id1>",
        "<id2>"
    ]
}

但现在我得到的是:
{
    "categories": [
        "<category1>,<category2>"
    ],
    "parts": [
        "<id1>,<id2>"
    ]
}

基本上,我正在寻找一种选项来传递分隔符参数到StringListField或添加一些自定义解析方法。
注意:
我知道,如果我将查询模式从?categories=<category1>,<category2>...更改为?categories=<category1>&categories=<category2>...,那么我会得到所需的结果,但我想坚持我的原始方法。

使用序列化器的特定原因是什么?在我看来,这似乎是一种反模式,并且我怀疑 is_valid() 在这种情况下是否返回 true。 - arjunattam
需要使用序列化器进行验证和解析。实际上它会返回 True,你可以试一下。顺便问一下,你会建议使用什么模式? - Szabolcs
当我在本地尝试时,得到了False。不过我还是可以建议如何使其工作:尝试重写StringListField的to_representation()方法。 - arjunattam
我肯定会在这里得到一个 True :) 是的,我考虑过那个,但希望有一个通用的最佳实践来解决这样一个常见的问题。 - Szabolcs
1个回答

4
我认为最好的方法是实现一个客户端to_representation():
def to_representation(self, instance):
    data = super(StringListField, self).to_representation(instance)

    data['parts'] = data['parts'].split(',') if isinstance(data['parts'], str) else data['parts']
    data['categories'] = data['categories'].split(',') if isinstance(data['categories'], str) else data['categories']

    return data

希望这能帮到你!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接