Configuration Guide¶
This document covers configuration options for the School Clubs Management System.
Overview¶
The application uses Flask configuration with sensible defaults. Most settings are configured in __init__.py during application factory initialization.
Application Configuration¶
Secret Key¶
Purpose: Signs session cookies and other security-related data.
Configuration:
Production Security
Never use the default secret key in production!
Generate a secure key:
Set via environment variable:
We use github pages for it where the actual keys are random and securely stored.Database Configuration¶
Database URI¶
Purpose: Specifies database connection.
Default: SQLite file in instance/data.db
basedir = os.path.abspath(os.path.dirname(__file__))
database_uri = "sqlite:///" + os.path.join(basedir, "instance/data.db")
app.config["SQLALCHEMY_DATABASE_URI"] = database_uri
Path: /deliverable-2/school_clubs/instance/data.db
Connection Options¶
Purpose: Optimize SQLite for web application use.
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
"connect_args": {
"timeout": 10, # Wait up to 10s for lock
"check_same_thread": False, # Allow multi-threading
},
"pool_pre_ping": True, # Test connections before use
"pool_recycle": 3600, # Recycle connections after 1 hour
}
Options Explained:
| Option | Value | Purpose |
|---|---|---|
timeout |
10 | Database lock timeout (seconds) |
check_same_thread |
False | Allow SQLite from multiple threads |
pool_pre_ping |
True | Verify connection health |
pool_recycle |
3600 | Recycle connections after 1 hour |
SQLite Limitations
SQLite is suitable for development and small deployments. For production at scale, consider PostgreSQL or MySQL.
Track Modifications¶
Disables SQLAlchemy event system to reduce overhead.
Flask-Login Configuration¶
Login View¶
Purpose: Redirect destination for unauthorized access.
Users attempting to access @login_required routes are redirected here.
Environment-Specific Configuration¶
Development¶
Characteristics:
- Debug mode enabled
- Detailed error pages
- Auto-reload on code changes
- SQLite database
Activation:
Settings:
Production¶
Characteristics:
- Debug mode disabled
- Generic error pages
- Optimized performance
- Secure secret key
- Production database (PostgreSQL recommended)
Activation:
export FLASK_ENV=production
export FLASK_APP=deliverable-2/school_clubs
export SECRET_KEY="your-secure-key-here"
gunicorn "school_clubs:create_app()"
Settings:
app.config["DEBUG"] = False
app.config["TESTING"] = False
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]
Testing¶
Characteristics:
- Separate test database
- Disable CSRF
- Fast test execution
Settings:
Usage:
# In test files
test_config = {
"TESTING": True,
"SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:",
"WTF_CSRF_ENABLED": False,
}
app = create_app(test_config)
Extension Configuration¶
Flask-Admin¶
Purpose: Admin panel settings.
URL: /admin/
Name: "School Admin" (appears in interface)
Flask-Bootstrap¶
Purpose: Bootstrap 5 integration.
Provides Bootstrap templates and macros.
Turbo Flask¶
Purpose: Enable real-time UI updates.
Used for dynamic login/signup error display without page reloads.
CLI Configuration¶
Custom Commands¶
Seed Database¶
Command: flask seed-db
Purpose: Populate database with test data.
Registration:
@app.cli.command("seed-db")
def seed_db_command():
from .seed import seed_database
with app.app_context():
seed_database()
Usage:
File Upload Configuration¶
Not Yet Implemented
File upload settings are planned for gallery posts but not yet configured.
Recommended Configuration:
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024 # 16 MB max
app.config["UPLOAD_FOLDER"] = os.path.join(basedir, "static/uploads")
app.config["ALLOWED_EXTENSIONS"] = {"png", "jpg", "jpeg", "gif"}
Helper Function:
def allowed_file(filename):
return "." in filename and \
filename.rsplit(".", 1)[1].lower() in app.config["ALLOWED_EXTENSIONS"]
Configuration Best Practices¶
Use Environment Variables¶
import os
class Config:
SECRET_KEY = os.environ.get("SECRET_KEY") or "dev-key-only"
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL") or \
"sqlite:///" + os.path.join(basedir, "instance/data.db")
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
# Production-specific settings
config = {
"development": DevelopmentConfig,
"production": ProductionConfig,
"default": DevelopmentConfig
}
Usage:
External Configuration File¶
.env file:
Load with python-dotenv:
from dotenv import load_dotenv
load_dotenv()
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY")
Configuration Hierarchy¶
- Defaults: Hard-coded in application
- Config File:
config.pyor similar - Environment Variables: Override config file
- Instance Folder:
instance/config.py(not in version control)
Database Initialization¶
Automatic Initialization¶
The application automatically creates tables on first run:
Note: This doesn't handle migrations. For production, use Flask-Migrate.
Manual Initialization¶
from school_clubs import create_app, db
app = create_app()
with app.app_context():
db.create_all()
print("Database tables created!")
Database Seeding¶
Populate with test data:
Defined in seed.py:
def seed_database():
# Create admin user
admin = User(
first_name="Admin",
last_name="User",
email="admin@example.com",
password_hash=generate_password_hash("admin123"),
user_type="admin"
)
db.session.add(admin)
# Create clubs, posts, etc.
# ...
db.session.commit()
Flask-Migrate Setup (Recommended)¶
For production environments, use Flask-Migrate for database migrations.
Installation¶
Configuration¶
Usage¶
# Initialize migrations
flask db init
# Create migration
flask db migrate -m "Initial migration"
# Apply migration
flask db upgrade
# Rollback
flask db downgrade
Logging Configuration¶
Development¶
Flask's default logger is sufficient:
Production¶
Configure structured logging:
import logging
from logging.handlers import RotatingFileHandler
if not app.debug:
file_handler = RotatingFileHandler(
"logs/school_clubs.log",
maxBytes=10240,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
"%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]"
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info("School Clubs startup")
Performance Tuning¶
Query Optimization¶
Enable query logging:
Caching¶
Consider Flask-Caching for frequently accessed data:
from flask_caching import Cache
cache = Cache(app, config={
"CACHE_TYPE": "simple",
"CACHE_DEFAULT_TIMEOUT": 300
})
@cache.cached(timeout=60)
def get_all_clubs():
return Club.query.all()
Security Headers¶
Recommended Headers¶
@app.after_request
def set_security_headers(response):
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "SAMEORIGIN"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
return response
Configuration Checklist¶
Development¶
- Use development secret key
- Enable debug mode
- Use SQLite database
- Seed database with test data
Production¶
- Set secure SECRET_KEY from environment
- Disable debug mode
- Use production database (PostgreSQL)
- Enable HTTPS
- Configure logging to file
- Set security headers
- Use environment variables for all secrets
- Enable Flask-Migrate for migrations
- Configure rate limiting
- Set up monitoring and alerts
Next Steps¶
- Installation Guide - Set up development environment
- Architecture - Understand application structure
- Deployment Guide - Deploy to production