Redirect While Passing Arguments

redirect while passing arguments

You could pass the messages as explicit URL parameter (appropriately encoded), or store the messages into session (cookie) variable before redirecting and then get the variable before rendering the template. For example:

from flask import session, url_for

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

(encoding the session variable might not be necessary, flask may be handling it for you, but can't recall the details)

Or you could probably just use Flask Message Flashing if you just need to show simple messages.

Flask - Redirect and passing arguments to the function

If all you want to do is serve the same template with the new language setting, then it helps to know that home_page() view is just a function. You can just call it:

@app.route('/lang=<language>')
def home_page_language(language):
return home_page(language)

Better still, you can register views under multiple routes, you don't actually need a second function here; just move the /lang=<language> registration to the home_page() function:

@app.route('/')
@app.route('/lang=<language>')
def home_page(language='en'):
return render_template(f"homepage - {language}.html")

Now / will use 'en', and /lang=foobar will call that same function with language='foobar'.

If you were hoping to actually redirect the browser back to the / URL (using a 30x Moved response), but at the same time keep the language setting, then you lose the information you stored in the URL path and have to record the language preference somewhere else. Most multilingual sites commonly store your language preference in a dedicated cookie, but you could also use the Flask session object (which also is cookie based in the default setup).

To redirect to a different URL, use the flask.redirect() function, then attach your cookie to the response object that that produces (using Response.set_cookie().

Your homepage will need to look for the language setting in the same cookie, it will not be part of the URL; I used a dedicated cookie here to store this information:

from flask import redirect, request, url_for

@app.route('/')
def home_page():
language = request.cookies.get('language', 'en')
return render_template(f"homepage - {language}.html")

@app.route('/lang=<language>')
def home_page_language(language):
redirected = redirect(url_for('home_page'))
redirected.set_cookie('language', language)
return redirected

If you were to store this information in the session object, you don't have to manually update the redirect response, the Flask framework handles that transparently for you:

from flask import session, redirect, url_for

@app.route('/')
def home_page():
language = session.get('language', 'en')
return render_template(f"homepage - {language}.html")

@app.route('/lang=<language>')
def home_page_language(language):
session['language'] = language
return redirect(url_for('home_page'))

How to pass arguments for return redirect(url()) in flask

When you provide keyword arguments to the url_for function, Flask automatically encodes your values into URI components and appends them to your request url.

Using your code as an example, doing this

msg11='Saved Successfully'
return redirect(url_for('editProfile', msg11=msg11))

Will yield this URL when passed to the editProfile route

/editProfile?msg11=Saved+Successfully

You can easily extract this value using Flask's built-in request object

from flask import request
# Inside of editProfile() route
msg11 = request.args.get('msg11', None)

That way, you can simply check if this value exists (calling get() is the same as the usual Python convention where a value of None will be returned if the value is not found) and pass it along to your HTML template.

Furthermore, using Jinja's functionality you can display the message only if it is not a None value by using something like this

{% if msg11 is not none %}
<h1>{{ msg11 }}</h1>
{% endif %}

A complete minimum example is outline below

app.py

from flask import Flask, render_template, redirect, url_for, request

app = Flask(__name__)

@app.route("/updateProfile", methods=["GET", "POST"])
def updateProfile():
msg11 = "Saved Successfully"
return redirect(url_for("editProfile", msg11=msg11))

@app.route("/editProfile")
def editProfile():
msg11 = request.args.get("msg11")
return render_template("editProfile.html", msg11=msg11)

if __name__ == "__main__":
app.run()

templates/editProfile.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>editProfile</title>
</head>
<body>
{% if msg11 is not none %}
<h1>{{ msg11 }}</h1>
{% else %}
<h1>msg11 has a value of None</h1>
{% endif %}
</body>
</html>

How can I pass arguments into redirect(url_for()) of Flask?

The redirect is fine, the problem is with the found route. You have several ways to pass values to an endpoint: either as part of the path, in URL parameters (for GET requests), or request body (for POST requests).

In other words, your code should look as follows:

@app.route('/found/<email>/<listOfObjects>')
def found(email, listOfObjects):
return render_template("found.html",
keys=email, obj=listOfObjects)

Alternatively:

@app.route('/found')
def found():
return render_template("found.html",
keys=request.args.get('email'), obj=request.args.get('listOfObjects'))

Also, your redirection should provide request parameters, not template parameters:

return redirect(url_for('found', email=x, listOfObjects=y))

How to pass arguments to HTML form using flask in case of redirection

So here's what I tried, I made a global dictionary and keep updating it wherever needed, now whenever I want to access some values I directly access it from my dictionary and render it using jinja templating. Apart from this method there are other ways as well like storing data in flask.session also one can use flask.flash() to render messages and access them using messages.get() function in their jinja template, but the problem with it is, it only provides a limited amount of size, if you pass an object or string of beyond that size, the browser simply ignores it and your messages will not be displayed because the message passed is in the form of browser-cookies. So, storing them in my global dictionary works for me:
Here's a small snippet of my final code which similarizes the code I have posted as question:

# Globals
info = {
'logged_in' : False,
'user' : {},
'tasks' : [],
'status' : {
'value' : '',
'positive' : True
}
}

def reset():
'''
function to reset the values of info object
'''
global info
info['logged_in'] = False
info['user'] = {}
info['tasks'] = []
info['status'] = {
'value' : '',
'positive' : True
}

# Setting Up Route for Register Page
@app.route('/register/', methods=['GET', 'POST'])
def register():
'''
function to register an account into the server and database
'''
global info
# Fetching Form Data
user = {
"name": request.form.get('name'),
"email": request.form.get('email'),
"username": request.form.get('username'),
"password": request.form.get('password'),
"tasks":[]
}
# Inserting data to Database and Redirecting to Login Page after Successful Registration
if user['name'] != None:
user['password'] = pbkdf2_sha256.encrypt(user['password'])
if mongo.db.appname.find_one({"username": user["username"]}):
info['status']['value'] = 'Username Already Taken'
info['status']['positive'] = False
return redirect(url_for('register'))
else:
mongo.db.appname.insert(user)
info['status']['value'] = 'Registered Successfully'
info['status']['positive'] = True
return redirect(url_for('login'))
status_val = info['status']['value']
positive_status = info['status']['positive']
reset()
return render_template('register.html', value = status_val, positive = positive_status)

How to pass a variable in `redirect(url_for())`

In first_hop, the parameters can be obtained using request.args.get('delay').

@app.route('/first_hop')
def first_hop():
x = request.args.get('delay')
print(x)
return redirect(url_for('second_hop'))


Related Topics



Leave a reply



Submit