Skip to content

Doing it all as an app

While blueprints are good for organising the code things will start to get messy as the app grows. We can use python modules to create a more organised structure.

  • Directoryflaskapp/
    • Directorystatic/
      • style.css
    • Directorytemplates/
      • index.html
      • base.html
    • __init__.py
    • blog.py
    • db.py

Creating the app

Create a new folder called flaskapp and add a __init__.py file to it. This file will be the entry point for the app.

flaskapp/__init__.py
from flask import Flask
import contextlib
import os
def create_app(test_config=None) -> Flask:
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskapp.sqlite"),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile("config.py", silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
with contextlib.suppress(OSError):
os.makedirs(app.instance_path)
@app.route("/ping")
def ping() -> str:
return "pong!"
return app
  1. The create_app function creates a new Flask app

    This function is automatically called by Flask when the app is run. It accepts an optional test_config parameter which can be used to pass in configuration values.

  2. Config is set

    The app is configured with a SECRET_KEY and a DATABASE path. The SECRET_KEY is used by Flask and extensions to keep data safe. The DATABASE is the path where the SQLite database file will be stored.

  3. A method to load external configuration

    The config.py file in the instance folder can be used to set configuration values. This is useful for setting values that should not be in version control.

  4. The instance folder is created

    The instance folder is created if it does not exist. This folder is used to store files that should not be in version control. with contextlib.suppress(OSError): is used to suppress the error if the folder already exists. This is similar to a try and except block.

  5. A ping route is added

    A simple route is added to check if the app is running. When the /ping route is accessed, the app will return pong!.

Running the app

To run our app we can run:

Terminal window
flask --app flaskapp run

Adding the blog blueprint

Create a new file called blog.py and add the following code to it.

flaskapp/blog.py
from flask import Blueprint
blog = Blueprint('blog', __name__)
@blog.route('/')
def index():
return 'Hello from the blog'

This blueprint will be used to handle all the blog related routes.

Registering the blueprint

Update the __init__.py file to register the blueprint.

flaskapp/__init__.py
# ensure the instance folder exists
with contextlib.suppress(OSError):
os.makedirs(app.instance_path)
from .blog import blog
app.register_blueprint(blog)
@app.route("/ping")
def ping() -> str:
return "pong!"

Setting up the database

Following from how we set up the blog blueprint, we can create a new file called db.py and add the following code to it.

flaskapp/db.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
db = SQLAlchemy(model_class=Base)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
def init_app(app: Flask):
db.init_app(app)
with app.app_context():
db.create_all()
  1. The Base class is created as a base for the databases

  2. The db object is created

    The db object is created using the SQLAlchemy class. The model_class parameter is set to the Base class to use it as the base for all models.

  3. The Post model is created

    The Post model is created with an id, title, and content column. The id column is the primary key. The title and content columns are set to be not nullable.

  4. The init_app function is created

    The init_app function is created to initialise the database. The db object is initialised with the app. The database is created with the create_all method.

In the __init__.py file, import the db module and call the init_app function.

flaskapp/__init__.py
# ensure the instance folder exists
with contextlib.suppress(OSError):
os.makedirs(app.instance_path)
from .db import init_app
init_app(app)
from .blog import blog
app.register_blueprint(blog)

With the database set up, we can now add a route to add a post to the database.

flaskapp/blog.py
from .db import Post, db
...
@bp.route("/add_post")
def add_post():
post = Post(title="Hello World", content="This is my first post")
db.session.add(post)
db.session.commit()
return "Post added"