7

I have a very basic question regarding URL changes. Let's assume I have a HTML page http://example.com/create that conatins a form with some input fields. From this input fields I want to create a python list which should be used to generate another HTML page http://example.com/show_list containing a list based on the python's list values.

So the view for http://example.com/create is:

@app.route('/create', methods=['GET', 'POST']) 
def create():

if request.method == 'POST':
    some_list = parse_form_data_and_return_list(...)
    return render_template( "show_list.html", some_list=some_list)  #here's the problem!

return render_template( "create.html")

Assume that parse_form_data_and_return_list(...) takes the user input and returns a list with some string values. I added a comment to the line that troubles me. I'll come back to it in a second but first give you the template of the page (http://example.com/show_list) that should be loaded AFTER the user input:

{% block content %}
<ul class="list">       
  {% for item in some_list %}
    <li>
        {{ item }}
    </li>
  {% endfor %}
</ul>
{% endblock content %}

Basically this works fine. The list values are "passed" to the Jinja template and the list is shown.

If you now again have a look to my route method you can see that I am only doing render_template to show the shwo_list page. For me this has one disadvantage. The URL will not be changed to http://example.com/show_list, but will stay at http://example.com/create.

So I thought about creating a own route for show_list and in the create() method calling redirect instead of rendering the next template directly. Like this:

@app.route('/show_list')
def tasklist_foo():
return render_template( "show_list.html" )

But in this case I don't see how I could pass the list object to show_list(). I could of course parse every single item of the list to the URL (hence post it to http://example.com/show_list), but that's not what I want to do.

As you already might have recognized, I'm pretty new to web developing. I guess I just use a wrong pattern or haven't found a simple API function that does the trick. So I kindly ask you to show me a way to solve my problem (shortly summerized): render the show_list template and change the URL from http://example.com/create to http://example.com/show_list using the list created in the create() method/route.

1
  • Why should /create redirect to a URL that won't work after you refresh the page? That isn't very RESTful or user-friendly. Can you explain your current scenario in more detail? Commented Aug 13, 2013 at 10:33

2 Answers 2

14

If the list isnt very long, you could pass it on the query string, say comma separated:

comma_separated = ','.join(some_list)
return redirect(url_for('show_list', some_list=comma_separated))
# returns something like 'http://localhost/show_list?some_list=a,b,c,d'

Then in the template in your view, you can iterate over them like so:

{% for item in request.args.get('some_list', '').split(',') %}
    {{ item }}
{% endfor %}

For longer lists, or if you didnt want to expose it on the query string, you could also store the list in the session:

session['my_list'] = some_list
return redirect(url_for('show_list'))

Then in the template:

{% for item in session.pop('my_list', []) %}
    {{ item }}
{% endfor %}
Sign up to request clarification or add additional context in comments.

1 Comment

Ahhh! The session dict. That's it. How could I have overseen this? I guess just too much new information for today. Thank you mate!
0

In addition to storing the list in the session you could also simply change your form action to post to the new route. Then process the form data from within the 'show_list' route and render your template.

Form heading:

<form action="{{ url_for('show_list') }}" method="post">

Updated show_list route:

@app.route('/show_list', methods=['GET', 'POST']) 
def show_list():
    if request.method == 'POST':
        some_list = parse_form_data_and_return_list(...)
        return render_template("show_list.html")
    else:
        # another way to show your list or disable GET
        return render_template("show_list.html")

I'm not necessarily opposed to using session storage, but I think it's cleaner to not use it as you don't have to worry about clearing your session variables.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.