Lecture 8.1 (March 8)

  • Working on A2 and P3
  • Q3 is after spring break

Resources

Loose Ends

  • Make log-in buttons be buttons
  • Drop excess cookie nonsense
  • Make user available in all templates
    • The session is directly available in Flask
    • There's also a 'Flask globals' object flask.g where you can stash stuff

Modularity in Python

So far, we have written all code in one big file.

Python lets you split code into separate files, called modules.

We import code from other modules.

By default, our current directory is searched, along with other Python code.

We're going to split our application into several modules:

init
This module contains the app object, along with other similar globals.
views
This module contains our @app.route URL handlers. It imports from init:
from init import app
myapp
A main module that pulls everything together: 1. Import init 2. Import views

And, of course, manage.py.

We can create other modules too, however we want to organize our code. Just a couple of rules:

  1. The myapp module needs to import every module that defines URL handlers, to make sure that they all get defined.
  2. To make manage.py work, it needs to also expose the app object

PyCharm will complain about unused imports; this is fine.

Note

If you read the Flask documentation on large applications, they suggest a somewhat different layout. Their layout breaks a common Python rule (with decent reason), but also requires more advanced understanding of the Python module system to understand, and does funny things to file paths.

Databases

We're now going to start using databases.

To do this, we are going to use SQLAlchemy and its Flask bridge. This allows us to write Python code to do basic (and many advanced) database operations.

Setting Up

First, we need to install it:

pip install flask-sqlalchemy

Then, we need to initialize SQLAlchemy in init.py:

from flask_sqlalchemy import SQLAlchemy
# … other init code
db = SQLAlchemy(app)

Defining Data

We now can define the kinds of data we want to store. We will create a module, models, that contains our database models.

Note

If you've heard of model-view-controller (MVC) architecture, this is it! The data is our model, the URL handlers are views, and effectively Flask is our controller.

In order to set up our data, we need to specify the different kinds of data we need to track, such as animals.

We define each kind of data as a Python class. It will then be used to create a database table.

class Animal(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50))
    location = db.Column(db.String(50))

This defines a data type Animal with three fields: an id (our objects should generally always have one of these), a name, and an animal.

There are a few rules:

  • Always have an id column that is a primary key, to identify your objects.
  • No lists - just numbers, strings, etc.

We'll see in a bit how to link data types together.

Querying Data

Now we will update the Flask app to query data from us:

  • Import models
  • Get animals by calling Animal.query.all()
  • Animals now have IDs, not just numbers — fix index.html
  • Get an animal with Animal.query.get(…)
  • Search animals with Animal.query.filter_by(name=name).first()

Adding Data

We can add:

  1. Create an object

    animal = Animal()
    animal.name = name
    animal.location = home
    
  2. Add it: db.session.add(animal)

  3. Commit: db.session.commit()
  4. Now animal.id has the animal ID

We can modify data too — just modify the object you got, then commit.

User Authentication

Work through how to create users and use bcrypt.