在 Python 中解析类似字典的 URL 参数

Posted

技术标签:

【中文标题】在 Python 中解析类似字典的 URL 参数【英文标题】:Parsing dictionary-like URL parameters in Python 【发布时间】:2012-12-28 16:21:48 【问题描述】:

我正在使用 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'
    

不幸的是,如果将 request.args 传递给 Flask 端点,您可以从这里得到:


    '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 所代表的对象,但在我能找到的规范中并没有提供这种类型的数据结构。

我开始编写一个函数,它接受一个参数字典并返回它们所代表的嵌套结构,但我很快意识到这是一个微妙的问题,而且肯定有人以前遇到过这个问题。

是否有人知道以我想要的方式解析这些参数的模块,或者我可能忽略的解析它们的优雅方式?

【问题讨论】:

只能是GET参数吗? JSON格式不好吗? ***.com/questions/7940085/…的可能重复 好吧,kendoUI 的 Grid 默认尝试使用 GET 参数,例如。您也许可以覆盖它,但它似乎也打破了 RESTful 范式——发送 JSON 需要一个 POST,并且您没有更新任何内容,只获取项目列表。 (我可能离基地很远,所以请随时纠正我) @NickODell 是的,这似乎是同一个问题,我在搜索中没有找到那个问题。尽管如此,答案并没有解决我的问题,它只是确认没有标准的方法来做到这一点。 KendoUI 的 Grid 控件由 DataSource 对象提供支持。 DataSource 允许通过 jQuery 的 $.ajax 方法配置如何通过 AJAX 进行 CRUD。看起来我可以使用 JSON,然后。尽管如此,这对于 Python 来说似乎还是很方便的,因为显然 php 和 RoR 都处理在查询字符串中传递的嵌套字典。 【参考方案1】:

我只是写了一个小函数来做到这一点:

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)

这应该适用于任何嵌套级别。

【讨论】:

很好,仔细观察后,它应该可以解决大多数情况。在某些情况下,查询应该给出列表而不是字典,但是 +1 最后,我使用了一个预先存在的库,而不是构建自己的库 - 但由于“手动执行”是我最终采用的方法,因此我接受了您的回答。作为参考,这是我使用的库:bitbucket.org/k_bx/jquery-unparam 这太棒了,就像 Datatables 服务器端东西的魅力一样:datatables.net/manual/server-side。我希望人们不要假设人们会使用 PHP 来编写他们的 ajax 调用,这是 2015 年的 fergodssake 这不适用于查询字符串中的数组,让我感到困惑的是 Python 没有内置它。 @JoshuaBarnett 给我一个例子,我会解决它!【参考方案2】:

前段时间发现了这个项目:https://github.com/bernii/querystring-parser

它专门用于做你想做的事。

但是,在 PHP 世界之外,GET(和 POST)参数的行为不同。就像它们通常使用多值字典来实现一样。因此,更好的想法可能是适应这种情况或找到一种兼容两个世界的方法。

或者,您可以真正在请求正文 (POST) 中使用 JSON 序列化数据,并将访问的资源视为控制器(执行某些操作的资源,在这种情况下是搜索某事,在您将一些数据传递给它之后) .

【讨论】:

“但是,在 PHP 世界之外,GET(和 POST)参数的行为不同。” - 是的,就像,根据 RFC!不幸的是,我正在使用我可以使用的工具的范围内工作。我终于找到了一种方法,通过使用 3rd 方库。晦涩难懂,打算采纳并妥善包装。 有谁明白为什么这不是urllib.parse.parse_qs 的标准行为?!【参考方案3】:

您也可以在 GET 请求中发送正文。 如果您只需要发送一些分层数据,则可能只是客户端的 json.dumps(data) 和服务器上的 json.loads(data)。

您可以在此处参考 httplib 文档中的此类做法: http://docs.python.org/2/library/httplib.html#httplib.HTTPConnection.request

【讨论】:

服务器应该假设 GET 请求的主体为空,我相信。 ***.com/questions/10298899/…

以上是关于在 Python 中解析类似字典的 URL 参数的主要内容,如果未能解决你的问题,请参考以下文章

urllib url解析学习

将url的查询参数解析成字典对象

将url的查询参数解析成字典对象

将url的查询参数解析成字典对象

Python函数中的参数

将url的查询参数解析成字典对象