In the previous article in this mini-series, we used Flask to build a simple website that contains "Home" and "About" pages using a generalized workflow that we can apply to other Flask-based web apps. In this lesson, I'll demonstrate how to add a Contact page that allows users to send you messages.
The code used in this article can be found on GitHub.
Flask doesn't come with many features off the shelf, making it easy to pick up and learn. There is no object-relational mapper for database interaction or admin interfaces to add and update content. It only offers a small set of functions, two of which we've already used—render_template().
Instead of shipping with extra functionality, Flask's extension model allows you to add functionality as needed. A Flask extension is a package that adds specific functionality to your app. For example, Flask-SQLAlchemy adds database support to your app, whereas Flask-Login adds login/logout support. You can find a full list of extensions in the Flask Extension Registry.
To create a contact page, we'll use Flask-WTF to handle and validate form data and Flask-Mail to email the form data to you.
Flask-WTF is an extension that handles and validates form data. What does that mean? Look at the following diagram:
A contact page will have fields for the user's name, email, subject, and message. In Flask, we'll POST the form to a function inside routes.py. This function is called the form handler. We'll run a few validation checks, and if any of the input does not pass muster, we'll refresh the page to display a message that describes the error. Once all validation checks pass, we'll use the form data for the next step: emailing the message to you, the website owner.
That's how form handling and validation work. Now where do we actually define the form? We could write HTML using the action attribute to a Python script. The Python script would mirror the form in order to capture each form field and validate the form field data. If we use this strategy, however, we'd essentially define the form twice—once for the front-end and once for the back-end.
It would be great to define the form only once: in the Python script. This is exactly what Flask-WTF allows us to do. We'll define the form just once in a Python script, and then we'll let Flask-WTF generate the form's HTML for us. The point of all of this is to separate presentation from content.
Enough chatter. Let's code.
As a first step, let's get back into the isolated development environment we created last time.
$ cd flaskapp<br>$ . bin/activate<br>
Now that we've entered and activated our development environment, we can safely install Flask-WTF:
pip install -U Flask-WTF<br>
Let's now define the form in a Python script. We already have routes.py, which maps URLs to functions. Let's not clutter it with unrelated code. Instead, create a new file called forms.py, and place it inside the app/ folder.
app/forms.py
from flask_wtf import FlaskForm<br>from wtforms import StringField, TextAreaField, SubmitField<br><br><br><br>class ContactForm(FlaskForm):<br> name = StringField("Name")<br> email = StringField("Email")<br> subject = StringField("Subject")<br> message = TextAreaField("Message")<br> submit = SubmitField("Send") <br>
We just created a form. What did we do? First, we imported a few useful classes from the Flask-WTF ContactForm, inheriting from the Name in an HTML file, you write from forms import ContactForm at the beginning of the script.
app/routes.py
from flask import Flask, render_template<br>from forms import ContactForm<br>
Next, configure Flask-WTF to handle a security exploit known as cross-site request forgery (CSRF). In a perfect world, your server would only process forms that belong to your web app. In other words, your server would only handle and validate the forms that you created. However, it is possible for an attacker to create a form on their own website, fill it in with malicious information, and submit it to your server. If your server accepts this malicious information, all sorts of bad things can happen next.
You can prevent a CSRF attack by making sure that the form submission originates from your web app. One way to do this is to keep a unique token hidden inside your HTML /contact, the function contact(), we first create a new instance of our contact form in line three and send it to a web template named contact.html in line four. We will create this web template shortly.
We still have some work to do here, though. The diagram above showed that if a GET request is sent to the server, the web page containing the form should be retrieved and loaded in the browser. If the server receives a POST request, a function should capture the form field data and check if it's valid. In Python terms, this logic can be expressed in an if...else logic to the render_template() in the previous article, so here we import one more Flask class named request determines whether the current HTTP method is a GET or a POST. Next is the contact() function (lines 9-13).
In the case of a POST request, a string indicating that the form has been posted will be returned.
This string is a temporary placeholder, and we'll replace it with real code in the final step of this article. Otherwise, if the request uses GET, we return the web template contact.html that contains the form.
The next step is to create the web template contact.html and put it inside the templates/ folder.
app/templates/contact.html
$ cd flaskapp<br>$ . bin/activate<br>
As with home.html and about.html, the contact.html template extends layout.html and fills the 'content' block with its own text. We first specify where to send the form data on submission by setting the action attribute to the /contact is mapped to the function contact() executes, where a variable named ContactForm class is sent to the web template contact.html.
Form validation is performed by using form validators. Fortunately, Flask-WTF comes with many useful, built-in validators that we can use right away. We'll put these validators in the DataRequired built-in validator from [validators= DataRequired()] to each form field to validate its presence. Notice that this validator is inside a Python list, meaning that we can easily add more validators to this list.
Next, let's require email addresses to match the pattern Email() validator requires the email_validator package to be installed, so install it with pip as follows:
pip install -U Flask-WTF<br>
Update app/forms.py as follows:
from flask_wtf import FlaskForm<br>from wtforms import StringField, TextAreaField, SubmitField<br><br><br><br>class ContactForm(FlaskForm):<br> name = StringField("Name")<br> email = StringField("Email")<br> subject = StringField("Subject")<br> message = TextAreaField("Message")<br> submit = SubmitField("Send") <br>
That does it for our form validation.
Looking back at the original diagram, if any validation check fails, the contact page should reload with an error message so that the user can fix the mistake and try again. This error message must only appear when validation fails and disappear when the mistake has been fixed.
Our next step is to send this sort of temporary error message to the user when validation fails. Flask makes this really easy by using its flash() function at the beginning of the script.
app/routes.py
$ cd flaskapp<br>$ . bin/activate<br>
After the contact form POSTs to the server, any validation failure should reload the form with a helpful error message. Otherwise, the input data can be used for future processing. Once again, this logic can be expressed in an if...else logic to the if request.method == 'POST': block.
app/routes.py
pip install -U Flask-WTF<br>
If any validation check fails, False. The error message Form posted, indicating the form has been successfully submitted.
Next, let's modify contact.html so that it can receive and display these temporary error messages. See the following block:
from flask_wtf import FlaskForm<br>from wtforms import StringField, TextAreaField, SubmitField<br><br><br><br>class ContactForm(FlaskForm):<br> name = StringField("Name")<br> email = StringField("Email")<br> subject = StringField("Subject")<br> message = TextAreaField("Message")<br> submit = SubmitField("Send") <br>
The function for loop. Add this code block to contact.html after
The above is the detailed content of Intro to Flask: Adding a Contact Page. For more information, please follow other related articles on the PHP Chinese website!