In the first part I covered the basics of a Flask application, routing, using templates, and file structure. In this part I will cover more advanced topics, like: using session for handling user authentication (for these I will cover Python annotations/decorators), using flash messages to provide feedback for the user, and how to setup and use custom error pages.

Python decorators/annotations

Python and many other programming languages have the concept of decorators -- also called annotations. In Python, decorators are basically functions, which receive a function as a parameter.

The code at first sight looks more complicated than it actually is. I defined the user_login_needed() function which receives the f function parameter. The @wraps is a convenience function which invokes the update_wrapper() method from Python’s functools library. The @wraps(f) is very expressive, since it really wraps the f function parameter with the method it annotates, decorated_function(). The decorated_function() is a method defined inside the user_login_needed() method. The decorated_function() redirects the request to the login page if the user is not logged in, OTHERWISE it invokes the f function parameter, passing in all the parameters – this is where all the magic happens. Using decorators, we basically insert a new layer between the invocation and execution of a method.

When the Flask app applies the routing rule and executes the index() method, it executes this line of code (simplified):

# no extra parameters passed since index does not take any parameters
return user_login_needed(index)

Creating login/logout for user authentication

Nowadays there is no Web application where the user does not need to sign in or register. For this purpose I created the login() and logout() methods. The decorator @user_login_needed was created to protect routes of the application from an unauthenticated user. All we need to do is annotate the methods which we want to protect with authentication.

Login

I added a new route and a new template for creating the login functionality.

I configured the http://localhost:5000/login route to only accept GET and POST HTTP requests, in any other case (for ex. PUT or DELETE requests) I redirect the user to the login page. If the request method is GET, then I simply return the rendered login.html page. In case the request method is POST (meaning the user pressed the Login button) I authenticate the user using the is_user_valid() method. If the user is valid I set the user_logged_in variable in the session to True – remember the user_login_needed decorator looks for this variable in the session. (NOTE: User validation and authentication should be done with proper encryption and respect for some basic software security principles and policies. Using the above code (is_user_valid method) for user authentication is insecure and should NOT be used in a real/production-like environment!)

The logout can be accessed only using GET requests, it sets the user_logged_in session variable to False, prints a debug message, pushes a flash messages to the template engine and returns the login page.

Flash messages

Flash messages provide a good way to send relevant information about what is happening on the webpage to the users. Flask provides a message system, which is accessed by the Jinja2 template engine. More details are on the help page.

Flushing messages can be done using the flush() method, as this can be seen in the logout() method’s code. The flushed messages are displayed in the login.html page, these can be accessed using the get_flashed_messages() method.

I created the method page_not_found() and specified to Flask using the @app.errorhandler(404), that in case there comes a request with an invalid route, it should execute the page_not_found() method. Inside the method I am returning an HTML page, but setting the HTTP Status Code to 404 – meaning the requested page was Not Found. More information on this topic can be found at Redirects and Errors help page.

I am a Software Engineer with over 7 years of experience in different domains(ERP, Financial Products and Alerting Systems). My main expertise is .NET, Java, Python and JavaScript.
I like technical writing and have good experience in creating tutorials and how to technical articles.
I am passionate about technology and I love what I do and I always intend to 100% fulfill the project which I am ...