0

I want to pass some arguments to my HTML form from flask when using redirect(url_for('Some End-Point')) instead of render_template(). I have already visited both of these questions

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

    but neither of them had the answer I am looking for. After some surfing I do find out that I have to use session for this but the problem is I don't know actually how to use that either. When I use this:
    return redirect(url_for('register', neg_resp="Username Already Taken"))
    the problem was, my output message do generate but came with URL instead and thus my jinja template doesn't receive it. Link from 120.0.0.1:5000/register/ changed to 120.0.0.1:5000/register/?=Username Already Taken
    And when I do this:
    return redirect(url_for('register'), neg_resp="Username Already Taken")
    An error gets generated, TypeError: redirect() got an unexpected keyword argument 'neg_resp' Here's my Python Code
# Setting Up Route for Register Page
@app.route('/register/', methods=['GET', 'POST'])
def register():
    # 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"]}):
            return redirect(url_for('register'), neg_resp="Username Already Taken")
        else:
            mongo.db.appname.insert(user)
            return redirect(url_for('login', pos_resp="Registered Successfully"))
    return render_template('register.html')

Error TypeError: redirect() got an unexpected keyword argument 'neg_resp'

Yashasvi Bhatt
  • 325
  • 3
  • 14

2 Answers2

1

This won't work:

return redirect(url_for('register'), neg_resp="Username Already Taken")

because it passes neg_resp as a parameter of redirect instead of url_for.

Here's a basic example of how to pass parameters between routes and to a template:

@app.route('/first/')
def first():
    return redirect(url_for('second', passed_value='string value'))

@app.route('/second/')
def second():
    passed_value = request.args.get('passed_value')
    return render_template('index.html', val_name=passed_value)
half of a glazier
  • 1,864
  • 2
  • 15
  • 45
  • It do work out but the problem is I am trying to pass a list, and I do convert it first into string and then convert it into list again but the string pattern is showing with url as well, can you tell me how to remove that extra unwanted part – Yashasvi Bhatt Apr 09 '21 at 08:07
  • `return render_template('index.html', mylist=vals)` where vals is the list, and `my_list = request.args.getlist('mylist')` should do the trick – half of a glazier Apr 12 '21 at 07:15
  • `render_template` only render html webpage, it does not alter the URL, that's why we can't use `request.args.getlist('mylist')` – Yashasvi Bhatt Apr 12 '21 at 08:29
  • Alternatively `return redirect(url_for('blueprint.route_name', mylist=vals))` would work – half of a glazier Apr 12 '21 at 08:32
  • `redirect()` works but the problem with it is if you try to send a value to redirect it will simply add that value to url, which I don't want because it might also display some secured data, see my answer which I have posted, it worked for me – Yashasvi Bhatt Apr 12 '21 at 08:42
0

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)
Yashasvi Bhatt
  • 325
  • 3
  • 14