python
50 lines · 7 steps
Class-based config in a Flask app factory
One base config plus per-environment subclasses feed a Flask app factory that wires up extensions and blueprints.
Explained by
highlit
1import os
2from datetime import timedelta
3
4
5class BaseConfig:
6 SECRET_KEY = os.environ.get("SECRET_KEY", "dev-only-insecure-key")
7 SQLALCHEMY_TRACK_MODIFICATIONS = False
8 JSON_SORT_KEYS = False
9 PERMANENT_SESSION_LIFETIME = timedelta(days=7)
10 RATELIMIT_STORAGE_URI = os.environ.get("REDIS_URL", "memory://")
11
12
13class DevelopmentConfig(BaseConfig):
14 DEBUG = True
15 SQLALCHEMY_DATABASE_URI = os.environ.get(
16 "DATABASE_URL", "sqlite:///dev.db"
17 )
18 SQLALCHEMY_ECHO = True
19
20
21class TestingConfig(BaseConfig):
22 TESTING = True
23 SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
24 WTF_CSRF_ENABLED = False
25
26
27class ProductionConfig(BaseConfig):
28 DEBUG = False
29 SQLALCHEMY_DATABASE_URI = os.environ["DATABASE_URL"]
30 SESSION_COOKIE_SECURE = True
31 PREFERRED_URL_SCHEME = "https"
32
33
34config = {
35 "development": DevelopmentConfig,
36 "testing": TestingConfig,
37 "production": ProductionConfig,
38}
39
40
41def create_app(config_name=None):
42 app = Flask(__name__)
43 config_name = config_name or os.environ.get("FLASK_ENV", "development")
44 app.config.from_object(config[config_name])
45 app.config.from_prefixed_env()
46
47 db.init_app(app)
48 migrate.init_app(app, db)
49 app.register_blueprint(api_bp, url_prefix="/api")
50 return app
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Inheriting from a base config keeps shared defaults in one place while each environment overrides only what differs.
- 2An app factory lets you build fresh, independently-configured app instances — essential for testing and multiple deployments.
- 3Reading secrets and URIs from the environment keeps configuration out of source control and portable across machines.
Related explainers
python
from flask import Blueprint, jsonify, request, abort v1 = Blueprint("users_v1", __name__) v2 = Blueprint("users_v2", __name__)
Versioning a Flask API with Blueprints
api versioning
blueprints
rest
Intermediate
7 steps
typescript
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { ConfigService } from '@nestjs/config';
How a JWT strategy authenticates in NestJS
authentication
jwt
passport
Intermediate
7 steps
python
import time import threading from enum import Enum from functools import wraps
Building a circuit breaker in Python
circuit-breaker
resilience
decorators
Advanced
7 steps
python
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector from django.core.cache import cache from django.db.models import F from django.http import JsonResponse
Ranked full-text search in Django
full-text-search
debouncing
caching
Advanced
9 steps
python
import time from flask import Flask, g, request
Timing requests with Flask hooks
middleware
request-lifecycle
instrumentation
Intermediate
5 steps
typescript
import { Injectable, Logger, OnApplicationShutdown } from '@nestjs/common'; import { InjectRedis } from '@nestjs-modules/ioredis'; import Redis from 'ioredis'; import { DataSource } from 'typeorm';
Graceful shutdown hooks in NestJS
graceful-shutdown
lifecycle-hooks
dependency-injection
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/class-based-config-in-a-flask-app-factory-explained-python-f207/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.