【问题标题】:Optional URL variables可选的 URL 变量
【发布时间】:2012-11-24 01:58:28
【问题描述】:

有没有办法在 Flask 中定义带有可选 URL 参数的 URL?本质上,我想做的是定义允许可选指定语言的规则:

/
/de -> matches / (but doesn't collide with /profile)
/profile 
/de/profile

我想我已经找到了一种方法来做到这一点,但这涉及到改变 Werkzeug 和 Flask 处理请求的方式(猴子修补或分叉框架源)。不过,这似乎是处理这个问题的一种过于复杂的方法。有没有更简单的方法可以做到这一点而我忽略了?

编辑:

根据 Brian 的回答,这是我想出的:

app.py:

from loc import l10n

def create_app(config):                                                                                                                 
    app = Flask(__name__)                                                                                                               
    app.config.from_pyfile(config)                                                                                                      

    bp = l10n.Blueprint()                                                                                                               
    bp.add_url_rule('/', 'home', lambda lang_code: lang_code)                                                                           
    bp.add_url_rule('/profile', 'profile', lambda lang_code: 'profile: %s' % 
        lang_code)
    bp.register_app(app)                                                                                                                

    return app  

if __name__ == '__main__':
    create_app('dev.cfg').run()

loc/l10ln.py

class Blueprint(Blueprint_):
    def __init__(self):
        Blueprint_.__init__(self, 'loc', __name__)

    def register_app(self, app):
        app.register_blueprint(self, url_defaults={'lang_code': 'en'})                                                                  
        app.register_blueprint(self, url_prefix='/<lang_code>')

        self.app = app

(我还没有从变量列表中提取lang_code,但很快就会这样做)

现在这只是热的恕我直言。

【问题讨论】:

    标签: python url-routing flask


    【解决方案1】:

    万一您不知道,您可以为一个视图注册多个路线。为每个视图都这样做可能会很痛苦,但它是可行的......

    DEFAULT_LANG = 'en'
    
    @app.route('/profile')
    @app.route('/<lang>/profile')
    def profile(lang=DEFAULT_LANG):
       pass
    

    或者,也许您可​​以实现自己的 route 装饰器,在这两种情况下自动调用 app.route...

    from flask import Flask
    
    app = Flask(__name__)
    
    DEFAULT_LANG = 'en'
    
    def lang_route(rule, **options):
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            app.add_url_rule(rule, endpoint, f, **options)
            app.add_url_rule('/<lang>%s' % rule, endpoint, f, **options)
            return f
        return decorator
    
    @lang_route('/profile') # also accepts '/<lang>/profile' automatically
    def profile(lang=DEFAULT_LANG):
        return lang
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    【讨论】:

    • 我认为这是一个很棒且非常彻底的答案。
    • 这不是一个糟糕的解决方案,但我认为蓝图更正确,因为它们旨在封装一组路由,并让您一次轻松地操作所有这些路由。 Flask docs recommend 使用蓝图进行 URL 国际化:“您可以通过编写自己的装饰器来进一步改进这一点,该装饰器在 URL 前加上语言代码,但更漂亮的解决方案是使用蓝图。”
    • @BrianMarshall,我为您的回答 +1 了...在您提供的链接中提供了很好的信息。
    • +1 我不知道您可以有多个视图!超级有帮助。
    • 你好,你能举出完整的例子吗?用html切换语言?
    【解决方案2】:

    蓝图可能适用于此,因为它们可以被多次注册。

    from flask import Flask, Blueprint
    
    app = Flask(__name__)
    bp = Blueprint('main', __name__)
    
    @bp.route('/')
    def hello(lang):
        return 'Hello ' + lang + '!'
    
    app.register_blueprint(bp, url_defaults={'lang': 'en'})
    app.register_blueprint(bp, url_prefix='/<lang>')
    
    if __name__ == '__main__':
        app.run()
    

    如果可行,请参阅 Flask 文档中的 Internationalized Blueprint URLs,了解如何避免在每个视图函数中指定 lang 参数。

    【讨论】:

    • 鉴于蓝图的(相对)新热度,这绝对是前进的道路
    • 你能给我举个更好的例子吗?我希望始终,mysite.com/en 和 mysite.com/ka 还通过 {{ translations.any_record_from_database }} 将数据库中的翻译消息提供给模板的方法
    猜你喜欢
    • 2018-05-07
    • 2014-01-11
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 2014-11-08
    • 2021-05-05
    相关资源
    最近更新 更多