Flask Design Patterns And Best Practices For Web Applications

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated March 7, 2024

This tutorial explains some of the common Flask design patterns and best practices to follow while designing web applications with examples:

Application design is an essential aspect of software development. An unplanned application design results in insurmountable technical debt. Therefore, whenever we want to scale our application, then it is okay to try out time tested design patterns.

Flask community has many such examples that can inspire you and impact your design decisions when you want to try out a few patterns for your application. Flask is so unopinionated and flexible that you might like to combine concepts from the existing patterns and create a new one.

=> Visit Here To Learn Flask From Scratch

Flask Patterns for Web Applications

Flask Design Patterns

For example, You will find many examples from the MVC pattern to Single Page Applications to SAAS pattern. You name the design paradigm, and it is already there tried by someone in the community and is freely available for you to try your hands on.

Enlisted below are a few of the repositories worth looking at.

Flusk

Flusk is an example that you can use to create big Flask applications that include SQLAlchemy, Docker, and Nginx. It has a beautiful logic separation to create backend, domain, views, and models into their respective layers.

It has excellent use of Flask Blueprints and follows the Factory design pattern. It is easy to create extensions in Flusk, and is further easy to containerize the application using Docker. Have a look at its source code here.

Cookiecutter Flask

Cookiecutter Flask is a flask template with features such as asset bundling and minification with webpacks. It has starter templates for user registration/authentication and is built on Bootstrap 4.

Cookiecutter is a command-line utility to create a Python package project. It means that if you use this template, you can publish your Flask application as PyPI too. This project is under active development.

It is worth evaluating at this link.

Flask Full

Flask full is one more power-packed boilerplate that makes use of Celery, MongoEngine, Signals, Shell commands, WebSocket, and eventlet. It is quite well integrated with Swagger API docs, and Sphinx docs.

Evaluate this project as its source. It is freely available here.

Flasky

For creating lightweight applications, you may want to consider Flasky. Flasky’s source code is available here. This repository was created by Miguel Grinberg, who has over 25 years of experience in web development.

He created Flasky to provide code examples for the concepts discussed in his book called Flask Web Development.

Whichever, Framework, or template you pick, all of these have some standard features and talk about those in their own ways. We here list some of those features and discuss them, and implement those using Flask-Appbuilder in our sample application of this tutorial series.

This tutorial discusses some more common patterns that you will find in almost all the web applications today and are nice to have in the kit of a web developer.

Flask Login Example

A web application usually requires Users to register and access the restricted part of the application based on the assigned privileges. The users have permission-based roles. For example, a public user doesn’t have permission to create another user. However, an Admin user has those permissions.

Sometimes, web applications automate the user registration and user creation by assigning them the default or pre-defined permissions.

Create User Offline

Let’s create a user using by using the flask fab create-user command. Once you use this command, you will get command-line prompts to give the details of the user account. Give the details similar to the ones shown below, and your User is created.

Role [Public]: 
Username: user1
User first name: User1       
User last name: Last1
Email: user1@sthwebsite.com
Password: 
Repeat for confirmation: 

## various logs 

2020-06-21 13:55:01,053:INFO:flask_appbuilder.security.sqla.manager:Added 
user user1
User user1 created.

Notice that at the end of the command output, the sqla.manager prints confirmation messages for user creation.

Now Access the Application, and log in with the details that you just entered. If you have created the User on the production database, then pass on those details to the person for whom you created this account.

Navigate to http://localhost:8080/login, and you will see the login form as shown below.

User login form
User login form

Once the user1 logs in, the User can see the Welcome message.

create_user_loggedIn
Welcome message for Logged In User

Create User Online

It might be impossible for us to create all the users offline. Moreover, it might require more technical expertise to use the flask fab create-user command in the production environment. You might get a requirement to take away some workload off from an Admin, who are most of the time tasked with the User creation.

Therefore, in our example web application, let’s allow users to register themselves.

We use Google’s reCAPTCHA service to prevent malicious actors from accessing the restricted parts of the application.

First, let’s register our domain on Google’s reCAPTCHA service and acquire the SITE key and SECRET key.

Step 1: Install Flask-Mail using the command below.

pip install Flask-Mail

Go to https://www.google.com/recaptcha/intro/v3.html and login as Admin using your Google Account.

Step 2: Choose the type of reCaptcha.

Googe_reCaptcha_type
Google reCaptcha Type (Note: Choose reCaptcha v2 if v3 doesn’t work)

Step 3: Give the domain for which you want to use Google’s reCaptcha.

Googe_reCaptcha_domain

Also, add the localhost in the list of allowed domains for this key and accept the terms and submit them. You can remove it later after the development of this feature.

Step 4: Note Down the SITE KEY which is also known as a public key.

Googe_reCaptcha_siteKey
Google reCaptcha Public Key

Step 5: Note Down the SECRET KEY that is also known as a private key.

Google reCaptcha Private Key
Google reCaptcha Private Key

Once you note down the keys as mentioned above, it is best to store them at a place where these can be referred and read in the config. For this tutorial, we have saved the values as environment variables as SITE_KEY and SECRET_KEY.

Now open the config.py and update it as shown below.

# Will allow user self registration
AUTH_USER_REGISTRATION = True# 

The default user self registration role
AUTH_USER_REGISTRATION_ROLE = "Public"# 

Config for Flask-WTF Recaptcha necessary for user registration
RECAPTCHA_PUBLIC_KEY = os.environ.get('SITE_KEY', None)
RECAPTCHA_PRIVATE_KEY = os.environ.get('SECRET_KEY', None)
# Config for Flask-Mail necessary for user registration

MAIL_PORT = 587
MAIL_USE_SSL = False
MAIL_SERVER = "smtp.gmail.com"
MAIL_USE_TLS = True
MAIL_USERNAME = "sthtestmail@gmail.com"
MAIL_PASSWORD = "Passw0rdqwerty"
MAIL_DEFAULT_SENDER = "sthtestmail0@gmail.com"

You might have to enable less secure access to your Google Account. Enable Account access at the below URLs if you get stuck in any Email related problems.

Google less secure Access
Google less secure Access
  1. https://accounts.google.com/DisplayUnlockCaptcha
  2. https://support.google.com/mail/?p=BadCredentials

Now on the Login page, we can see an additional user Registration button. Once you click on registration, we can see many fields along with the reCaptcha Challenge.

Google reCaptcha Challenge
Google reCaptcha Challenge

Once you register with your email and pass the reCaptcha challenge, you will see a confirmation message, as shown below.

Registration Confirmation Message
Registration Confirmation Message

If the email that you gave during registration is valid, then you will receive the account activation email similar to the one shown in the below image.

Account Activation Email
Account Activation Email

Flask Admin

If you have read the other tutorials in this Flask tutorial series, then you will notice that we have taken the benefit of the in-built security that comes with Flask-Appbuilder. The views that we added using add_view_no_menu are not protected. However, the views that we added based on DataModels are automatically protected for an Admin user.

Alternatively, we could make use of Flask-Admin, which mostly would have achieved a similar outcome. Flask-Admin too, let’s define views in an Object-Oriented manner. A webpage on the frontend represents a method on a view class that we explicitly add to the interface.

In this tutorial, we do not use Flask-Admin. Instead, we take the path of achieving the same results with more speed and skipping the necessity of knowing about security build around Login, Auths, Roles, and permissions. It was possible as we used Flask-Appbuilder.

Both Flask-Appbuilder as well as Flask-Admin have their pros and cons. In the case of Flask-Admin, we must know that there are no existing security assumptions, and you can create apps based on your security model. To know more about Flask-Admin, please visit here and go through suitable examples.

Flask File Upload

Almost all web applications these days have the requirements of storing and serving files. A typical pattern for them is to save the files at a path on the Server, with some information to do the operation on the stored file and keep in Application Models and views.

We are going to work on a similar example. Let’s modify our Song Model with additional features.

In the models.py file enter the following code.

from flask import Markup, url_for
from flask_appbuilder.models.mixins import FileColumn
from flask_appbuilder.filemanager import get_file_original_name
from flask_appbuilder import Model
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship

class Song(Model):
    id = Column(Integer, primary_key=True)
    title = Column(String(200), nullable=False)
    rating = Column(Integer)
    album_id = Column(Integer, ForeignKey('album.id'))
    # for storing MP3 file of the song
    song_file = Column(FileColumn, nullable=False)
    album = relationship("Album")

    def __str__(self):
        return self.title

    def download(self):
        return Markup(
                '<a href="' +
               url_for("SongsView.download", filename=str(self.song_file)) +
                '">Download</a>'
        )

    def file_name(self):
        return get_file_original_name(str(self.song_file))

We have modified our previously created Song model by adding a new column of type FileColumn. Furthermore, we have added two more columns that will be added to the SongsView to display the File Name and a link to download the uploaded file.

Flask url_for method has been used along with Markup to display the Download as a link. Also, we have used the get_file_original_name method from the Flask-Appbuilder as the file name is stored by concatenating it with a UUID to avoid collisions between the same file names.

Modify views.py with the below-given code to update the corresponding SongsView.

class SongsView(ModelView):
    datamodel = SQLAInterface(Song)    

    label_columns = {"file_name" : "File Name", "download": "Download"}
    list_columns = ["title", "file_name", "download"]
    show_columns = ["title", "file_name", "download"]

In SongsView class, we have mentioned the new labels that need to be displayed, and we want to list only the columns mentioned in the specified list.

Here you need to remember that we have modified a database model by adding a column to the model. The corresponding table in the database doesn’t have this new column. Therefore, we will remove the app.db file, as we are working on the SQLite database since the last tutorial.

Alternatively, we could also use the flask db migrate command and make necessary changes to the version file, and use flask db upgrade to update the table. However, the change we introduced is minimal, and we can recreate the application database and User.

We recommend that in production, consider using the Flask-Migrate commands whenever you make any changes to the Database Schema of your application.

Use the below commands to remove the database file and create the admin user again.

rm app.db
flask fab create-db
flask fab create-admin

Now login into the application with the Admin credentials, and you will see the modified SongsView as shown in the below image.

Songs View with File Field
Songs View with File Field

Add a song with a file.

Add a Song with a file
Add a Song with a file

Once you save the file, the columns in the View will look as shown below.

Columns in SongsView
Columns in SongsView

Notice the following values in config.py. The uploaded files will be stored on this path on the Server. For this tutorial, it will be uploaded to the machine on which we are developing this sample application.

Check the upload path, as mentioned in config.py. The files are stored with the UUID’s, as shown below.

Flask File Upload example
Flask File Upload example

Flask HTTPS

As far as development is concerned, we may continue to run our Flask Application running without HTTPS. From a security standpoint, HTTPS ensures that communication happens between legitimate Client and Server.

This encrypted communication requires that trust is established between a Client and a Server, using a CA-signed certificate with a pair of public and private keys. Please read more about it here

In this tutorial, we will let you know the methods to develop Flask based websites using HTTPs during development.

The quickest and easiest way to include HTTPS during development is to use an adhoc ssl_context, as mentioned below in run.py. However, please install pyopenssl using pip in the environment.

app.run(host='0.0.0.0', port=8080, debug=True, ssl_context='adhoc')

After adding ssl_context, when you navigate to https://localhost:8080/, you will get a warning raising doubt about the validity of the certificate being used in this communication. Moreover, navigation to http://localhost:8080/ will not work anymore.

Thus, this approach is a bit cumbersome, and it will require you to keep accepting this request whenever you restart your development server.

You need to click on unsafe access to continue working, as shown below.

Proceed Unsafe
Proceed Unsafe

Alternatively, to develop with the https features, we can pass the path to the certificate and key in a Python Tuple to the ssl_context parameter in the run method. However, to adopt this approach, you will have to generate a self-signed certificate and a key by using the command below.

openssl req -x509 -newkey rsa:4096 -nodes -out mycert.pem -keyout mykey.pem -days 365

Give appropriate values for the asked queries.

Self Signed Certificate Command
Self Signed Certificate Command

We have left all default values. Now stop the development server, and pass the path certificate and the key path as shown below.

app.run(host='0.0.0.0', port=8080, debug=True, ssl_context=('mycert.pem', 'mykey.pem'))

This approach is also similar to the previous method of using Adhoc ssl_context. However, in this case, the details persist for a longer time. We have mentioned 365 days. You can specify the expiry to the days that you need. Moreover, these files can be shared with the other team members if you are developing in a team.

In the production environment, the certificates are issued by the CA, and Miguel Grinberg discusses some use cases here. We recommend that you read more details on that page.

Conclusion

In this tutorial, we have discussed some patterns that web developers follow while developing features related to Flask Login, Flask Admin, Flask File Upload, and Flask HTTPS. We have provided code examples, and the readers can try that too.

In our next tutorial, we will cover the concepts of extending Flask and see how to create REST API based features. Moreover, we will discuss how we can use Twitter API inside Flask.

=> Explore The Flask Training Series Here

Was this helpful?

Thanks for your feedback!

Leave a Comment