2012-11-24 7 views
6

Czy istnieje sposób definiowania adresów URL z opcjonalnymi parametrami URL w Flasku? Zasadniczo, co chciałbym zrobić, to określić zasady, które pozwalają na ewentualnie określonych językach:Opcjonalne zmienne URL

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

Chyba wymyśliliśmy sposób, aby to zrobić, ale to wiąże się zarówno do dokonywania zmian i jak Werkzeug Flask obsługuje żądanie (albo łatanie małpy, albo rozwidlenie szkieletu). Wydaje się to być zbyt skomplikowanym sposobem radzenia sobie z tym problemem. Czy istnieje łatwiejszy sposób na zrobienie tego z pominięciem?

Edit:

oparciu o odpowiedź Briana, oto co wymyśliłem:

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 

(Nie mam jeszcze okazji wyciągnąć lang_code z listy zmiennych, ale wkrótce to zrobię)

Teraz to tylko gorące imho.

Odpowiedz

7

Plany mogą w tym pomóc, ponieważ mogą być rejestrowane wiele razy.

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() 

Jeśli to działa, zobacz Internationalized Blueprint URLs w dokumentacji kolbie przez taki sposób, aby uniknąć określania lang argument w każdej funkcji widoku.

+0

Zdecydowanie sposób na imho, biorąc pod uwagę (względną) nową gorliwość planów –

10

Na wypadek gdybyś nie wiedział, możesz zarejestrować wiele tras dla widoku. Ból może być to zrobić dla każdego widoku, ale jest to wykonalne ...

DEFAULT_LANG = 'en' 

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

A może można zaimplementować własną route dekorator, które automatycznie wywołuje app.route dla obu scenariuszy ...

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) 
+0

Myślę, że jest to świetna i niezwykle dokładna odpowiedź. – jdotjdot

+0

100% właściwą drogą. – sberry

+1

To nie jest złe rozwiązanie, ale uważam, że plany są bardziej poprawne, ponieważ są zaprojektowane do enkapsulacji zestawu tras i pozwalają łatwo manipulować wszystkimi tymi trasami naraz. [Dokumentacja Flask docs] (http://flask.pocoo.org/docs/patterns/urlprocessors/#internationalized-application-urls) za pomocą planów internacjonalizacji adresów URL: "Możesz to jeszcze poprawić, pisząc własny dekorator, który przedrostkuje adresy URL z kodem językowym, ale najpiękniejszym rozwiązaniem jest używanie wzorca ". –