web-dev-qa-db-fra.com

rediriger en passant des arguments

En fiole, je peux faire ceci:

render_template("foo.html", messages={'main':'hello'})

Et si foo.html contient {{ messages['main'] }}, la page affichera hello. Mais que se passe-t-il si un itinéraire mène à foo:

@app.route("/foo")
def do_foo():
    # do some logic here
    return render_template("foo.html")

Dans ce cas, le seul moyen de se rendre à foo.html, si je veux de toute façon que cette logique se produise, consiste à utiliser une variable redirect:

@app.route("/baz")
def do_baz():
    if some_condition:
        return render_template("baz.html")
    else:
        return redirect("/foo", messages={"main":"Condition failed on page baz"}) 
        # above produces TypeError: redirect() got an unexpected keyword argument 'messages'

Alors, comment puis-je obtenir que cette variable messages soit transmise à la route foo, afin que je n’aie pas à réécrire le même code logique que celui-ci calcule avant de le charger?

36
limp_chimp

Vous pouvez transmettre les messages en tant que paramètre d'URL explicite (codé de manière appropriée) ou stocker les messages dans la variable session (cookie) avant la redirection, puis obtenir la variable avant le rendu du modèle. Par exemple:

def do_baz():
    messages = json.dumps({"main":"Condition failed on page baz"})
    session['messages'] = messages
    return redirect(url_for('.do_foo', messages=messages))

@app.route('/foo')
def do_foo():
    messages = request.args['messages']  # counterpart for url_for()
    messages = session['messages']       # counterpart for session
    return render_template("foo.html", messages=json.loads(messages))

(coder la variable de session peut ne pas être nécessaire, le flacon peut la gérer pour vous, mais ne peut pas rappeler les détails)

Ou vous pourriez probablement simplement utiliser Flask Message Flashing s'il vous suffit d'afficher des messages simples.

52
Tommi Komulainen

Je suis un peu confus. "foo.html" n'est que le nom de votre modèle. Il n'y a pas de relation inhérente entre le nom de la route "foo" et le nom du modèle "foo.html".

Pour atteindre l'objectif de ne pas réécrire le code logique pour deux routes différentes, je définirais simplement une fonction et l'appellerais pour les deux routes. Je n'utiliserais pas la redirection, car cela redirige le client/navigateur, ce qui les oblige à charger deux pages au lieu d'une, pour vous faire gagner du temps de codage - ce qui semble méchant:

Alors peut-être:

def super_cool_logic():
    # execute common code here

@app.route("/foo")
def do_foo():
    # do some logic here
    super_cool_logic()
    return render_template("foo.html")

@app.route("/baz")
def do_baz():
    if some_condition:
        return render_template("baz.html")
    else:
        super_cool_logic()
        return render_template("foo.html", messages={"main":"Condition failed on page baz"})

J'ai le sentiment que quelque chose me manque et qu'il existe un meilleur moyen de réaliser ce que vous essayez de faire (je ne sais pas vraiment ce que vous essayez de faire).

2
Ben

Je tiens à mentionner que url_for ne peut pas être utilisé tant qu'il n'est pas ajouté aux importations de flacon! 

J'ai passé une heure à essayer de comprendre pourquoi cela ne fonctionnerait pas car personne ne l'a mentionné dans plusieurs sites Web !!!

Ajoutez url_for à la liste des importations comme ceci:

from flask import Flask, render_template, request, redirect, session, url_for
1
saltydog

J'ai trouvé qu'aucune des réponses ici ne s'appliquait à mon cas d'utilisation spécifique, alors j'ai pensé partager ma solution. 

Je cherchais à rediriger un utilisateur non authentifié vers la version publique d'une page d'application avec tous les paramètres URL possibles. Exemple:

/ app / 4903294/my-great-car? email = coolguy% 40gmail.com à

/ public / 4903294/my-great-car? email = coolguy% 40gmail.com

Voici la solution qui a fonctionné pour moi. 

return redirect(url_for('app.vehicle', vid=vid, year_make_model=year_make_model, **request.args))

J'espère que cela aide quelqu'un!

0
Nick Woodhams