Series: Building a Social Network with Flask & Stream – Part 3
This is the third installment of a tutorial series focusing on how to create a full-stack application using Flask and Stream. Originally, this article was going to cover the creation of the initial database models for your app, as well as handling registration/login and other convenience functions for users, but given the sheer amount of content there is to cover, I’m going to split it into two parts.
This first part is going to cover setting up User models and permissions, and next week we will launch into creating the views and forms for registration and login! Check out the GitHub repo here to help you follow along!
Getting Started
As usual, we’re going to start by installing few packages to get us rolling:
Flask-WTF (What The Form) is a form and validation package to aid in the creation of forms, by adding in some extra features like CSRF tokens and alerts.
Flask-Login is a session management package that helps by handling user authentication, allowing us to verify users so that we can pass the correct information to them.
Flask-Mail is an email package that sends out emails to users; we will use it to send confirmations to users upon registration, as well as to aid with some of the convenience functions that I mentioned earlier, like changing a user’s email or password.
Finally, Flask-Migrate is a database versioning tool that lets us keep a record of changes made to our database tables, by handling additions and subtractions of columns from tables.
And By Extension
Since we’ve loaded in new libraries, the first thing we should do is go to the extensions.py
file and update it:
In order to initialize the packages in a specific app context when it's created, we will need to include them in our create_app function in the __init__.py file
.
Configure It Out
Given the new packages we’ve installed, our next step will be to edit our config.py
file to set some of their options:
Now that we have our configuration up, we can put our packages to work!
Next Steps
Our first task is to establish our User and Permissions tables. This section will largely draw on Miguel Grinberg’s Flasky application; if you’re not familiar with its incredible awesomeness, you can check it out here.
Let’s start off by setting up the Users table:
Better to Ask Permission
Now that we have a basic User class set up, our next step will be to set up Permissions, so that we can differentiate between our basic users, moderators and administrators. Doing so will let us segment parts of the site based on permission:
This table and its functions will provide the permissions assignment we need for our application, making sure that our users are only able to access the things they should have access to, and letting us build functions for our moderators and admins to edit questionable content and boot toxic users!
Anon and On
Right now, if a permissions check is done on a user who doesn’t have an account, we’ll get a nasty little error. Our final step in setting permissions is to define a class for anonymous users:
And, with that, this portion of our database modeling is finished (for now). Though, we’ll be back next week to set up user convenience functions, like changing your password or email!
Not Just For Decoration
Now that we have our Permissions table and functions set up, our next step will be to set up a decorator function that checks specific permissions for a route. For this, we will create a decorator.py
file in the app
directory:
The first decorator will allow you to set a specific level of permissions needed to access a route or function, while the second is used to verify that the user has admin-level permissions. I find that this helps to differentiate the look of admin-only resources, as well as to follow Python stylistic guidelines (explicit is better than implicit, etc).
Migration Patterns
Our tables are set, however, this won’t be the last time that we need to change our database; a frequently-used package, called flask-migrate
, will help by versioning changes, allowing us to upgrade and downgrade through different versions, in order to apply or revert those changes. We already installed the package, itself, at the beginning; now we just have to bring it into the application.py
file:
While bringing flask-migrate
into the application.py
file, I also took the liberty of updating the shell context to be able to reference the database and models that we have established in models.py, so we don’t have to manually import them every time. To round it out, I created a handy little deploy tool for the command line that will let us quickly upgrade our database to the latest revision and create or update user roles.
Our next step is to initialize the migrate
package for our project, as well as create our initial migration and upgrade the database:
Last but not least, we will go into the shell and insert all the roles for our users:
Time for an Upgrade!
Before we finish this tutorial, I wanted to take a minute to create a landing page for users to be wowed with when they first arrive! Right now, if you were to launch your app, it would still return your basic “Hello World!” text, so a basic html file would be a large upgrade. We’ll start by creating the index.htm
file in app/templates
:
Now that we have the template, we have to reference it in the route (in app/main/views.py
), to have the template rendered:
Flask uses a templating service called jinja2
; if you have developed with Django before it may seem very similar. Jinja allows you to define blocks of code, like your title and page content, as well as import other files and variables from your app.
Sanity Check
To make sure everything is working as it should, we’ll boot up our development server (flask run
) and navigate to localhost.
If you get an ugly error, you might have to set the Flask app, again, with:
set FLASK_APP=application.py
Final Thoughts
With that, we have constructed our database model for users with automatic avatar construction, password setting, and a complete permissions system with anonymous users! Additionally, we have covered initializing Flask-Migrate to track changes to our models, and, in our next installment, we will get into generating and validating confirmation tokens that we will send in an email when users sign up, along with some new user routes for our authentication and some basic navigation.
Thanks for reading and happy coding!
Note: The next post in this series can be found here.