1

我正在使用 webargs 从request.argsMarshmallow 中解析参数并将它们作为参数传递给 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's 生成 URL 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 失败。

我无法更改客户端生成 URL 的方式,所以我想坚持使用DelimitedField. 我怎样才能url_for生成相同的样式?

4

1 回答 1

2

没有为查询字符串中的键指定多个值的标准。url_forFlask、浏览器和许多其他 Web 技术使用您使用和看到的“重复键”样式request.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 或其他方式解析任何传入的逗号分隔值。相反,从您的客户端生成重复键样式可能更容易。

于 2018-01-16T21:55:08.523 回答