You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中request.GET获取参数时出现额外引号导致无法解析的问题

Django中request.GET获取参数时出现额外引号导致无法解析的问题

我通过Django的request.GET传递参数时,得到的字典里的statuses值被当成了带引号的字符串,没法直接解析成列表来访问内部数据,这让我很头疼。

具体情况

  • 重定向到端点的编码数据:
/turnalerts/api/v2/statuses?statuses=%5B%7B%27conversation%27%3A+%7B%27expiration_timestamp%27%3A+%271735510680%27%2C+%27id%27%3A+%2757f7d7d4d255f4c7987ac3557bf536e3%27%2C+%27origin%27%3A+%7B%27type%27%3A+%27service%27%7D%7D%2C+%27id%27%3A+%27wamid.HBgNMjM0OTAzOTc1NjYyOBUCABEYEjdCMTJFNUZDNzNFQjkxQ0IyRQA%3D%27%2C+%27pricing%27%3A+%7B%27billable%27%3A+True%2C+%27category%27%3A+%27service%27%2C+%27pricing_model%27%3A+%27CBP%27%7D%2C+%27recipient_id%27%3A+%272349039756628%27%2C+%27status%27%3A+%27sent%27%2C+%27timestamp%27%3A+%271735424268%27%7D%5D
  • 请求对象:
<rest_framework.request.Request: GET '/turnalerts/api/v2/statuses?statuses=%5B%7B%27conversation%27%3A+%7B%27expiration_timestamp%27%3A+%271735510680%27%2C+%27id%27%3A+%2757f7d7d4d255f4c7987ac3557bf536e3%27%2C+%27origin%27%3A+%7B%27type%27%3A+%27service%27%7D%7D%2C+%27id%27%3A+%27wamid.HBgNMjM0OTAzOTc1NjYyOBUCABEYEjdCMTJFNUZDNzNFQjkxQ0IyRQA%3D%27%2C+%27pricing%27%3A+%7B%27billable%27%3A+True%2C+%27category%27%3A+%27service%27%2C+%27pricing_model%27%3A+%27CBP%27%7D%2C+%27recipient_id%27%3A+%272349039756628%27%2C+%27status%27%3A+%27sent%27%2C+%27timestamp%27%3A+%271735424268%27%7D%5D'>
  • 通过request.GET获取到的数据:
{'statuses': "[{'conversation': {'expiration_timestamp': '1735510680', 'id': '57f7d7d4d255f4c7987ac3557bf536e3', 'origin': {'type': 'service'}}, 'id': 'wamid.HBgNMjM0OTAzOTc1NjYyOBUCABEYEjdCMTJFNUZDNzNFQjkxQ0IyRQA=', 'pricing': {'billable': True, 'category': 'service', 'pricing_model': 'CBP'}, 'recipient_id': '2349039756628', 'status': 'sent', 'timestamp': '1735424268'}]"}

能看到statuses的值被当成了字符串(外面的双引号是Python字符串的标识,不是实际参数内容),没法直接像列表那样访问内部字段。

预期结果

我希望拿到的是这样的结构,statuses是一个列表:

{'statuses': [{'conversation': {'expiration_timestamp': '1735510680', 'id': '57f7d7d4d255f4c7987ac3557bf536e3', 'origin': {'type': 'service'}}, 'id': 'wamid.HBgNMjM0OTAzOTc1NjYyOBUCABEYEjdCMTJFNUZDNzNFQjkxQ0IyRQA=', 'pricing': {'billable': True, 'category': 'service', 'pricing_model': 'CBP'}, 'recipient_id': '2349039756628', 'status': 'sent', 'timestamp': '1735424268'}]}

我的视图代码

class StatusesPayloadLayerView(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)
    
    def get(self, request, *args, **kwargs):
        payload = request.GET
        data = payload.dict()
        try:
            error_code = data['statuses'][0]['errors'][0]['code']
        except KeyError:
            error_code = None

现在因为statuses是字符串,执行这段代码会直接报类型错误,根本没法访问内部的errors字段。我查过URL编码规则,编码后的内容里并没有表示双引号的%22,完全搞不懂为啥会变成字符串。


解决办法

其实这个问题很简单:Django的request.GET本质是QueryDict,它会把所有URL参数都当成字符串存储,不会自动帮你解析成列表、字典这类Python数据结构。你看到的双引号只是Python打印字符串时的格式,不是实际参数里的内容,核心是要把这个字符串形式的列表转成真正的Python列表。

这里给你两种靠谱的处理方式:

方式一:用ast.literal_eval(推荐)

ast.literal_eval是Python标准库的工具,能安全地把字符串形式的Python字面量(比如列表、字典)转成实际的Python对象,而且支持单引号,完美适配你的场景:

import ast

class StatusesPayloadLayerView(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)
    
    def get(self, request, *args, **kwargs):
        payload = request.GET
        data = payload.dict()
        error_code = None
        try:
            # 把字符串解析成Python列表
            statuses_data = ast.literal_eval(data['statuses'])
            # 现在可以正常访问内部数据了
            error_code = statuses_data[0]['errors'][0]['code']
        except (KeyError, IndexError, SyntaxError):
            # 处理解析失败、找不到字段的情况
            error_code = None
        return # 这里根据你的需求返回响应

方式二:用json模块

如果想用json模块,因为标准JSON要求键和字符串必须用双引号,所以需要先把字符串里的单引号替换成双引号,再解析:

import json

class StatusesPayloadLayerView(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)
    
    def get(self, request, *args, **kwargs):
        payload = request.GET
        data = payload.dict()
        error_code = None
        try:
            # 替换单引号为双引号,转换成标准JSON格式
            json_str = data['statuses'].replace("'", '"')
            statuses_data = json.loads(json_str)
            error_code = statuses_data[0]['errors'][0]['code']
        except (KeyError, IndexError, json.JSONDecodeError):
            error_code = None
        return # 这里根据你的需求返回响应

为啥会出现这种情况?

当你通过URL传递类似列表/字典的复杂结构时,Django不会自动识别并解析,只会把它当作普通的字符串参数存储。你看到的双引号只是Python在展示字符串时的标识,不是实际参数里的内容,所以必须手动解析成Python数据结构才能正常使用。

备注:内容来源于stack exchange,提问作者user24242514

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 11:58:03