Skip to content

📝 Portfolio Tracker (SQLite) — Architecture

A Flask web application built following the official Flask tutorial, demonstrating core Flask design patterns: application factory, blueprints, request context, and session management.


Technology Stack

Layer Technology Purpose
Language Python 3.13+ Application runtime
Web Framework Flask 3.1.2 Routes, templates, request handling
Database SQLite3 (built-in) Lightweight relational database
Templates Jinja2 Server-side HTML rendering
Password Hashing Werkzeug PBKDF2-based password security
Timezone pytz UTC → Asia/Singapore conversion
CLI Click (Flask dependency) init-db command
Testing pytest + coverage Unit tests and code coverage
Build System Flit Modern Python packaging

Application Structure

app_portfolio_tracker/
├── __init__.py          # Application factory (create_app)
├── auth.py              # Authentication blueprint
├── blog.py              # Blog/content blueprint
├── db.py                # Database utilities
├── logic.py             # Business logic (extensible)
├── schema.sql           # Database schema
├── static/
│   └── style.css
└── templates/
    ├── base.html        # Base template with navigation
    ├── auth/
    │   ├── login.html
    │   └── register.html
    └── blog/
        ├── index.html
        ├── create.html
        └── update.html

Architecture Breakdown

1. Application Factory Pattern

The entry point is create_app() in __init__.py — the Flask application factory:

def create_app(test_config=None):
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        SECRET_KEY='dev',
        DATABASE=os.path.join(app.instance_path, 'portfolio_tracker.sqlite'),
    )
    # Blueprint registration, database init, URL routing
    return app

Why this pattern?

  • Enables multiple app instances (testing vs. production)
  • Allows dynamic configuration injection
  • Prevents circular imports
  • Standard Flask best practice

2. Blueprint Architecture

The application is split into two blueprints for modular organisation:

Blueprint URL Prefix Responsibility
auth /auth Registration, login, logout, access control
blog / (root) Post CRUD, listing, author verification

3. Database Layer

Function Purpose
get_db() Returns request-scoped SQLite connection via Flask's g object
close_db() Teardown handler — closes connection at end of request
init_db() Executes schema.sql to create tables
init_db_command() CLI: flask init-db

Schema:

CREATE TABLE user (
    id       INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    password TEXT        NOT NULL
);

CREATE TABLE post (
    id        INTEGER PRIMARY KEY AUTOINCREMENT,
    author_id INTEGER   NOT NULL,
    created   TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    title     TEXT      NOT NULL,
    body      TEXT      NOT NULL,
    FOREIGN KEY (author_id) REFERENCES user (id)
);

4. Authentication Flow

  • Registration → Validate input → Hash password (PBKDF2) → Insert user
  • Login → Verify credentials → Store user_id in signed session cookie
  • Per-requestload_logged_in_user() runs before every request, loads g.user from session
  • Access control@login_required decorator redirects unauthenticated users

5. Request Lifecycle

Example: User creates a new blog post.

  1. Browser sends GET /create
  2. load_logged_in_user() fires → loads user from session into g.user
  3. @login_required checks g.user → redirects to login if missing
  4. create() renders the form template
  5. User submits POST /create with form data
  6. View validates input → inserts post with g.user['id'] as author → commits
  7. close_db() teardown closes the SQLite connection
  8. Redirect to index

Key Design Patterns

Pattern Implementation
Application Factory create_app() creates configured Flask instance
Blueprint Modular route organisation (auth, blog)
Request Context g.user, g.db — per-request data, auto-cleaned
Session Management Signed cookies, session['user_id']
Decorator @login_required, @bp.before_app_request
Template Inheritance base.html → child templates extend blocks

Screenshots

Coming soon

Screenshots of the blog interface will be added here.