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
typescript
import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; import localeFrExtra from '@angular/common/locales/extra/fr'; import localeDe from '@angular/common/locales/de';
Locale-aware bootstrapping in Angular
i18n
localization
dependency-injection
Intermediate
8 steps
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 steps
typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import * as Joi from 'joi';
Validating env config at boot in NestJS
configuration
schema-validation
environment-variables
Intermediate
8 steps
java
@Component @Converter public class EncryptedStringConverter implements AttributeConverter<String, String> {
Transparent column encryption in Spring & JPA
encryption
aes-gcm
jpa-converter
Advanced
10 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { InjectRepository } from '@nestjs/typeorm';
A cache-aside country lookup in NestJS
cache-aside
dependency-injection
batch-lookup
Intermediate
8 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.