Introduction to Flask (Part I)

For the next few weeks in HacKSU, I’ll be teaching a series on Flask, a Python micro-framework. We’ll be creating a JSON REST API (don’t worry if you have no idea what that means) for a link-sharing website similar to HackerNews. In Week One, we got Python and Flask installed, setup a database, and got close to a working user login system. Here’s how we did it:

Installation

We’ll need Python and pip installed before we can get started. To check if you already have python installed, run these two commands in your terminal application:

$ python --version
$ pip --version

If you get something like “Python 2.7.6" and “pip 6.0.6", you’re good to go. If not, follow these installation instructions for Python (pip is included with Python these days).

The last thing we need to do is install virtualenv, which will allow us to create executable files and libraries that are kept local to our project folder. Once you have pip working, virtualenv is easy to install:

$ sudo pip install virtualenv

Omit the “sudo” if you’re on Windows. If installation is successful, you should be able to run:

$ virtualenv --version

And get something like “12.0.5". That’s enough boring stuff for now, let’s continue…

Project Setup

Getting the Files

The next thing we need to do is setup our project. I’ve created a blank file structure starting point for us to work with, so let’s get this GitHub repository cloned (the link takes you to the repository at the commit before the meeting began).

Once you have that folder on your local machine, go ahead and open it up in your text editor of choice. You’ll see a folder structure that looks like this:

app/
users/
__init__.py
controller.py
model.py
__init__.py
.gitignore
config.py
run.py

Here’s the basic breakdown of what each of these files is going to do:

run.py: A script that starts a server on http://127.0.0.1:3000

config.py: Some basic configuration for our app (we’re not going to worry about what this does)

app/: A folder containing all of our routes and models; the meat of our application.

app/__init__.py: A file that creates our Flask instance and sets up our database. It contains basically everything that we want to be able to import from elsewhere in our app.

app/users/: A folder containing our users “module”. All code that does something related to logging in, registering, etc. goes in here.

app/users/controller.py: The routes for users (I’ll explain what routes are soon).

app/users/model.py: A model is a class that represents a table in our SQLite database. This one represents a single user.

Creating a Virtual Environment

Remember that “virtualenv” thing we installed earlier? Now’s the time it comes in handy. Open your terminal, cd into the directory of your project, and run this command:

$ virtualenv flask

This will create a folder named “flask” and place some Python and pip executables inside. Next, we’ll activate this virtualenv:

Mac/Linux:
$ . flask/bin/activate
Windows:
> flask\scripts\activate

Install Libraries

Finally, we need to install some libraries that we’ll be utilizing later in the project. It’s pretty simple now that we’re all set up:

$ pip install Flask Flask-SQLAlchemy Flask-HTTPAuth Flask-Migrate

Let’s code.

Getting Hello, World

Create a Server

The first thing we need to do is create a server in app/__init__.py and a script that runs it in run.py. Open up app/__init__.py and place some code:

# Import Flask and SQLAlchemy (a database library)
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
# Create our app instance
app = Flask(__name__)
app.config.from_object(‘config’)
# Create our db instance
db = SQLAlchemy(app)
# Import modules that we’ll be working with
from .users import controller

Then open up run.py:

# Import the app instance we just made
from app import app
# Run the app on port 3000 (you can change the port to something else if you'd like)
app.run(port=3000, debug=True)

Finally, we’ll create our first route to display Hello, World! A route is a method that runs when a certain URL is requested. So, if we browse to http://localhost:3000/hello, the ‘/hello’ route will be called. In app/users/controller.py, go ahead and place this:

from app import app
# Define our first route
@app.route(‘/’)
def index():
return ‘Hello, World!’

To see what we just did, go back to your terminal and type:

$ python run.py

Then, visit http://localhost:3000/ in your browser, and see your beautiful new page.

Make a Login System

Create a Model

We need to tell SQLAlchemy what a user looks like. In app/users/model.py, we can easily do that:

# Import our db instance and a helper for hashing passwords
from app import db
import hashlib
# A helper method to hash a password
def hash(password):
return hashlib.sha224(password).hexdigest()
# Create a class that represents each user
class User(db.Model):
# An id field that will automatically increment every time we add someone to the database
id = db.Column(db.Integer, primary_key=True)
# A username field
username = db.Column(db.String(64), nullable=False, unique=True)
# A password field
password = db.Column(db.String(64), nullable=False)
  # A constuctor function for creating our new user
def __init__(self, username, password):
self.username = username
self.password = password
  # A little method that saves our user
def save(self):
db.session.add(self)
db.session.commit()
  # A method that returns a dictionary representing the user
def serialize(self):
return {
‘id’: self.id,
‘username’: self.username
}

Run Migrations

Each time we make changes to our models, we need to tell SQLAlchemy that things aren’t the same as they were before. Let’s make a script that lets us easily do that in one simple command.

Start by creating a new file called migrate.py in the root of the project directory. Don’t worry too much about what we’re doing here, but go ahead and place this code inside:

from app import app, db
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command(‘db’, MigrateCommand)
from app.users import model
if __name__ == ‘__main__’:
manager.run()

In your terminal, you can now run

$ python migrate.py db init

to create a migrations folder. Then, run:

$ python migrate.py db migrate

to make Flask-Migrate detect the new users table. Finally, run

$ python migrate.py db upgrade

to apply these changes to your SQLite database. If you look at your project folder, you’ll see a file called app.db. This is your SQLite database.

Create Routes

Finally, we need to create some routes that will let us add users. Put this inside app/users/controller.py:

# Import our app, some helpers, and our model
from app import app
from flask import jsonify, request
from .model import User, hash
# Define a route for /users that returns all users in our database
@app.route(‘/users’)
def users():
# Get an array of dictionaries of all users
users = [u.serialize() for u in User.query.all()]
# Return a json string containing this array
return jsonify({‘users’: users})
# Define a route to register a new user
@app.route(‘/users/register’, methods=[‘POST’])
def register():
# Create a new User instance, getting the username and password from our POST variables
# Also, hash the password before saving it
user = User(
request.form[‘username’],
hash(request.form[‘password’])
)
# Save the new user to our database
user.save()
# Return the newly created user
return jsonify(user.serialize())

Go ahead and restart the server:

$ python run.py

and view http://localhost:3000/users in your browser. You’ll see a JSON string with an empty array. Now, let’s test out the register route, by using Postman (a Chrome extension) to post data to our route. If you’re using Postman, use http://localhost:3000/users/register as the URL, use POST as the HTTP verb, and make two key value pairs:

username: person
password: secret

If you refresh http://localhost:3000/users, you’ll see the newly created user.

Conclusion

That’s all we got to this week. Next week, we’ll finish up the users module by making a few methods that allow us to make certain routes require user login. Then, we’ll dive into creating the rest of our API, by adding functionality such as sharing links, up/down voting, and commenting.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.