Python Friday #38: Forms for Your Flask App

From small contact forms to whole applications for data collection, forms are an important part of most web applications. Let us look how we can work with forms in Flask.

This post is part of my journey to learn Python. You can find the other parts of this series here.

 

A simple form

For this example, I use a simple contact form that accepts a name, an email address and a message:

To deliver this form for the URL /contact I need a view function like this one:

If I now visit the /contact page I can see my form:

The contact form

However, if I click on the submit message button, I get this error:

Method not allowed

 

Accepting POST

By default, Flask only allows GET requests on its view functions. To submit this form, we want to use the POST method and need to allow it explicit:

I decided to create another view function to process the form data. You could do that in the same function, but that makes it harder to understand what is going on.

We can access the data from the form using the request.form dictionary:

We now can store this data or send it by email instead of printing it to the command line. Before we do that, we have to check if everything works in the browser. If we now click on submit, we get a success message:

We could submit our form

Despite the working feature, this solution has a severe problem that we will only notice in production. If we hit reload (or F5) in our browser, we get this warning message:

The browser tries to send the form again

The form data is still in the browser and that could lead to big problems when we use a form in an online store. It is a lot better to fix this problem right away than to hope no one ever hits F5.

 

Post/Redirect/Get pattern

There is a design pattern called Post/Redirect/Get to solve our problem of resubmitting a form. Instead of handling the POST request and delivering the success message in the same view function, we split those two responsibilities into two different view functions and create a redirect between them. This needs a little bit more code but saves us from the troubles of resubmitted forms.

For this pattern we need to modify our contact_post() view function and replace the call to render_template() with a redirect (the Post/Redirect part of the pattern) to another view function:

We can redirect the user to any other existing view function or, as I prefer, to a specific one for this form (that will do the GET part of the pattern):

Since we return the same template, the behaviour for the user looks exactly like before. However, when you now make a refresh, you only reload the /thanks page – and not data is sent to the application:

127.0.0.1 – – [**** 21:00:49] “GET /thanks HTTP/1.1” 200 –
127.0.0.1 – – [**** 21:00:50] “GET /thanks HTTP/1.1” 200 –
127.0.0.1 – – [**** 21:00:51] “GET /thanks HTTP/1.1” 200 –
127.0.0.1 – – [**** 21:00:51] “GET /thanks HTTP/1.1” 200 –

 

Next

Preventing the user from posting the same data over and over again is only one step to prevent bad data in our application. Another important step is to validate the user input which I cover in the next post.

1 thought on “Python Friday #38: Forms for Your Flask App”

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.