使用Flask的url_for在URL中生成列表

时间:2018-01-16 19:15:08

标签: python flask query-string marshmallow webargs

我使用webargs解析来自request.args的Marshmallow参数,并将它们作为参数传递给Flask视图。我的客户端使用逗号分隔列表来表示键的多个值:

/queues/generate?queue_id=4&include_ids=1,2,3

要解析这个,我使用Marshmallow的DelimitedList字段。

from marshmallow import Schema, fields
from webargs import use_args
from webargs.fields import DelimitedList

class GenerationParamsSchema(Schema):
    queue_id = fields.Integer(required=True)
    include_ids = DelimitedList(fields.Integer(), required=False)

@queues.route('/generate_content', methods=['GET'])
@use_args(GenerationParamsSchema(strict=True))
def generate_content_count(generation_params):
    ...

但是,如果我使用Flask' url_for生成网址,则会为每个值生成重复的密钥:

url_for('queues.generate', queue_id=4, include_ids=[1, 2, 3])
/queues/generate?queue_id=4&include_ids=1&include_ids=2&include_ids=3

使用DelimitedList字段解析此字段仅捕获第一个值。更改为List字段会再次正确捕获值。因此,我的Flask URL失败,或者我的客户端URL失败。

我无法更改客户端生成网址的方式,因此我希望坚持使用DelimitedField进行解析。如何让url_for生成相同的样式?

1 个答案:

答案 0 :(得分:1)

There's no standard for specifying multiple values for a key in a query string. Flask,浏览器和许多其他网络技术使用"重复键"您使用url_forrequest.args看到的样式。您的客户选择使用不同的风格。

如果您希望url_for生成分隔的样式,则需要预先处理传递给url_for的值。在url_for周围写一个包装,然后使用它。

from flask import url_for as _url_for

@app.template_global()
def url_for(endpoint, **values):
    for key, value in values.items():
        if isinstance(value, (tuple, list)):
            values[key] = ','.join(value)

    return _url_for(endpoint, **values)

请注意,requests.args只能理解重复键样式,因此您必须使用webargs或其他方式解析任何传入的逗号分隔值。可能更容易从客户端生成重复键样式。