agconti
agconti

Reputation: 18093

Flask url_for() with multiple parameters

The Problem:

I have an a input button in a form that when its submitted should redirect two parameters , search_val and i, to a more_results() function, (listed below), but I get a type error when wsgi builds.

The error is: TypeError: more_results() takes exactly 2 arguments (1 given)

html:

 <form action="{{ url_for('more_results', past_val=search_val, ind=i ) }}" method=post>
    <input id='next_hutch' type=submit value="Get the next Hunch!" name='action'>
 </form>

flask function:

@app.route('/results/more_<past_val>_hunches', methods=['POST'])
def more_results(past_val, ind):
    
    if request.form["action"] == "Get the next Hunch!":
        ind += 1 
        queried_resturants = hf.find_lunch(past_val) #method to generate a list
        queried_resturants = queried_resturants[ind]
        return render_template(
                               'show_entries.html', 
                                queried_resturants=queried_resturants, 
                                search_val=past_val,
                                i=ind 
                               )

Any idea on how to get past the build error?

What I've tried:

Creating link to an url of Flask app in jinja2 template

for using multiple paramters with url_for()

Build error with variables and url_for in Flask

similar build erros

As side note, the purpose of the function is to iterate through a list when someone hits a "next page" button. I'm passing the variable i so I can have a reference to keep incrementing through the list. Is there a flask / jinja 2 method that would work better? I've looked into the cycling_list feature but it doesn't seem to able to be used to render a page and then re-render it with cycling_list.next().

Upvotes: 18

Views: 52484

Answers (3)

Avre Williams
Avre Williams

Reputation: 1

try to serialize your kwargs with json.dumps() like this

<form action="{{ url_for('more_results',kwargs=json.dumps({"past_val":search_val,"ind":i} ) }}" method=post>

On the flask side,

@app.route('/results/more_<kwargs>_hunches', methods=['POST'])
def more_results(kwargs):
   kwargs = json.loads(kwargs)
   past_val=kwargs['past_val']
   ind = kwargs['in']

alternatively, you could use flask.session or flask.g to manage these variables with the context of the session or request eg. assign the value to a session['past_val'] = search_val and use the session attributes anywhere including with Jinja template like so {{session['past_val']}}

Upvotes: 0

plaes
plaes

Reputation: 32716

It's also possible to create routes that support variable number of arguments, by specifying default values to some of the arguments:

@app.route('/foo/<int:a>')
@app.route('/foo/<int:a>/<int:b>')
@app.route('/foo/<int:a>/<int:b>/<int:c>')
def test(a, b=None, c=None):
   pass

Upvotes: 38

Amber
Amber

Reputation: 526603

Your route doesn't specify how to fill in more than just the one past_val arg. Flask can't magically create a URL that will pass two arguments if you don't give it a two-argument pattern.

Upvotes: 9

Related Questions