在Python中解析字典样式的URL参数

10 投票
3 回答
5105 浏览
提问于 2025-04-17 13:13

我正在用Python实现服务器端的过滤功能,以支持KendoUI的Grid组件。

我遇到的问题是,默认生成的AJAX调用似乎和Flask自带的URL解析器以及Python的urlparse模块不兼容。

这里有一个我遇到麻烦的查询字符串的例子:a=b&c=d&foo[bar]=baz&foo[baz]=qis&foo[qis]=bar

我想要的结果是:

{
    'a': 'b',
    'c': 'd',
    'foo': {
        'bar': 'baz',
        'baz': 'qis',
        'qis': bar'
    }
}

不幸的是,如果把这个传给Flask的接口,你会得到这样的request.args

{
    'a': 'b',
    'c': 'd',
    'foo[bar]': 'baz'
    'foo[baz]': 'qis'
    'foo[qis]': 'bar'
}

更糟糕的是,实际上,这种结构可能会有好几层。比如,如果你想过滤foo这一列,只显示值为'bar'的行,结果会是这样的:

{
    'filter[logic]': 'and',
    'filter[filters][0][value]': 'bar',
    'filter[filters][0][field]': 'foo',
    'filter[filters][0][operator]': 'eq'
}

我查阅了相关的标准(RFC),它要求查询字符串只能包含“非层级”的数据。虽然我认为这指的是URI所表示的对象,但在我找到的规范中并没有规定这种数据结构。

我开始写一个函数,想把参数字典转换成它们所代表的嵌套结构,但我很快意识到这是个复杂的问题,肯定有人之前也遇到过这个麻烦。

有没有人知道有没有模块可以按照我想要的方式解析这些参数,或者有没有我可能忽略的优雅解析方法?

3 个回答

0

你也可以在GET请求中发送数据。如果你需要发送的只是一些层次结构的数据,可以在客户端用json.dumps(data)把数据转换成JSON格式,然后在服务器端用json.loads(data)把它转换回来。

你可以在httplib的文档中查看相关的做法,链接在这里: http://docs.python.org/2/library/httplib.html#httplib.HTTPConnection.request

4

不久前,我发现了这个项目:https://github.com/bernii/querystring-parser

这个项目正好是为了满足你的需求而设计的。

不过,在PHP以外的环境中,GET和POST参数的处理方式是不同的。通常,它们会用多值字典来实现。所以,可能更好的办法是适应这种方式,或者找到一种能兼容两种环境的方法。

另外,你也可以在请求体中使用JSON格式的数据(POST),然后把访问的资源当作控制器来处理(这个资源会在你传递一些数据后执行某些操作,比如搜索东西)。

9

我刚写了一个小函数来完成这个任务:

from collections import defaultdict
import re
params = {
    'a': 'b',
    'c': 'd',
    'foo[bar]': 'element1',
    'foo[baz]': 'element2',
    'foo[qis]': 'element3',
    'foo[borfarglan][bofgl]': 'element4',
    'foo[borfarglan][bafgl]': 'element5',
}

def split(string, brackets_on_first_result = False):
    matches = re.split("[\[\]]+", string)
    matches.remove('')
    return matches

def mr_parse(params):
    results = {}
    for key in params:
        if '[' in key:
            key_list = split(key)
            d = results
            for partial_key in key_list[:-1]:
                if partial_key not in d:
                    d[partial_key] = dict()
                d = d[partial_key]
            d[key_list[-1]] = params[key]
        else:
            results[key] = params[key]
    return results
print mr_parse(params)

这个函数应该可以处理任何嵌套的层级。

撰写回答