【问题标题】:Flask redirect url_for changing type of parameterFlask redirect url_for 改变参数类型
【发布时间】:2015-10-26 07:21:16
【问题描述】:

我在 Flask/python 中有以下代码,其中涉及一个变量 years,它是一个整数列表。但是,当我使用return redirect(url_for(... 时,年份变为 unicode,如果是 [2015, 2014],则变为 '[','2','0','1','5',' ' 等。 ..

@main.route('/search', methods=('GET','POST'))
def fysearch():
    form = SelectYear()
    if form.validate_on_submit():
        years = form.years.data
        return redirect(url_for('.yearresults', years=years))
    return render_template('select_year.html', form=form)

当我打印以上年份每个元素的类型时,它是我想要的普通 int。一旦它被传递到重定向 url_for,那就是年变成 unicode 的时候。

@main.route('/searchresults/<years>')
def yearresults(years):
    page = request.args.get('page', 1, type=int)
    print type(years)
    pagination = Grant.query.filter(Grant.fy.in_(years)).\
            paginate(page, per_page=current_app.config['POSTS_PER_PAGE'],
        error_out=False)
    return render_template('yearresults.html', years=years, entries=pagination.items, pagination=pagination

我知道有一些方法可以在将整数列表传递给 yearresults(years) 之后将其恢复为整数列表,例如 years=json.loads(years) 或替换 [ 和 ] 并拆分,但我想知道是否有是解决此问题的另一种方法。我在 url 路由中考虑过一个转换器,但我不确定它是如何工作的,因为我使用的是烧瓶蓝图。 提前致谢!

【问题讨论】:

    标签: python flask url-routing


    【解决方案1】:

    函数url_for 返回一个 URL,它实际上是一个字符串 - 你不能将一个整数列表混合到一个实际上是一个字符串的值中(在更好的语言/框架中,你会得到一个类型错误,更多的工作就是方式但不太容易出现像您正在经历的概念错误)。您可以简单地通过返回url_for('.yearresults', years=years) 的结果来检查,并看到该值类似于/yearresults/%5B2014%2C%202015%5D。显然,year 的值是一个字符串,因为它是默认转换器(因为您没有定义一个)。因此,懒惰的方法是使用 JSON 或某种字符串格式对 years 进行编码,然后在 yearresults 处理程序上对其进行解码,但是使用 werkzeug 包中的 converter 是正确的想法。

    无论如何,把它们放在一起你可以做这样的事情:

    from werkzeug.routing import BaseConverter
    from werkzeug.routing import ValidationError
    
    class ListOfIntConverter(BaseConverter):
        def __init__(self, url_map):
            super(ListOfIntConverter, self).__init__(url_map)
    
        def validate(self, value):
            if not isinstance(value, list):
                return False
    
            for i in value:
                if not isinstance(i, int):
                    return False
    
            return True
    
        def to_python(self, value):
            try:
                return [int(i) for i in value.split(',')]
            except (TypeError, ValueError) as e:
                raise ValidationError()
    
        def to_url(self, value):
            if not self.validate(value):
                # Or your specific exception because this should be from the
                # program.
                raise ValueError
            return ','.join(unicode(v) for v in value)
    
    app.url_map.converters['listofint'] = ListOfIntConverter
    
    @app.route('/years/<listofint:years>')
    def years(years):
        return '%d, %s' % (len(years), years)
    

    这样做的好处是当该路由的输入不匹配时(即有人为&lt;years&gt; 提供字符串)直接生成404,并避免[]% 编码形式,和 来自基于 JSON(或 repr)的编码(与 2014,2015 相比,%5B2014%2C%202015%5D 看起来很难看)。

    将转换器放入特定的蓝图(以及为此进行的单元测试)是您的练习。

    【讨论】:

      猜你喜欢
      • 2015-01-13
      • 1970-01-01
      • 2014-07-22
      • 1970-01-01
      • 2015-11-21
      • 2020-10-08
      • 1970-01-01
      • 2016-07-08
      相关资源
      最近更新 更多