SAT.AUG.15
2026
22:21:25

Doing it all as an app

A simple website built using flask

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.

  • flaskapp/
    • static/
      • style.css
    • templates/
      • index.html
      • base.html
    • __init__.py
    • blog.py
    • db.py

Most Python projects use this structure to organise their code and should be used as for all your projects.

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.

    If this were ever going to be run in production or as a normal application the secret key should be very secure and not just DEV.

  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:

flask --app flaskapp run

We can also run the app in debug mode by adding --debug to the end.

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"