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:

https://gist.github.com/Porter97/7aaa710284162e490bd2e11c21941e5d

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:

https://gist.github.com/Porter97/3a0d2fc61ea59dadcecf49e61474d844

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.

https://gist.github.com/Porter97/07733bb1290d70b79e3af74e99ee9e78

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:

https://gist.github.com/Porter97/96c617759d60a1ceac5410335e87a955

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:

https://gist.github.com/Porter97/f6187581676a80dce21753979db34d12

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:

https://gist.github.com/Porter97/ff4a6e1bee5ef0830d3ab0069115a187

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:

https://gist.github.com/Porter97/185e6e9f681a240c442070f6578d315c

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:

https://gist.github.com/Porter97/5a8c8ffab26f1021c507bf81075e9fe4

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:

https://gist.github.com/Porter97/afaad17bb1c55ac8c08c28dea3d00ee2

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:

https://gist.github.com/Porter97/3120555e268b44b69ebd686da1db1a77

Last but not least, we will go into the shell and insert all the roles for our users:

https://gist.github.com/Porter97/f28ce03cae10e206f6df5261ed65bdea

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:

https://gist.github.com/Porter97/aebf34795b219090ff30411ecd8b2119

Now that we have the template, we have to reference it in the route (in app/main/views.py), to have the template rendered:

https://gist.github.com/Porter97/bf0fbf716b48eb20fb9d59161400ecd2

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.

Tutorials

Chat

Feeds