Skip to main content

Flask Code Organization

When you start building Flask applications beyond simple "Hello World" examples, you'll quickly realize the importance of proper code organization. A well-structured Flask project improves maintainability, makes collaboration easier, and helps your application scale gracefully over time.

Why Code Organization Matters​

As Flask follows the microframework philosophy, it doesn't enforce a specific project structure. This flexibility is both a blessing and a curse:

  • Advantage: You can adapt it to your specific needs
  • Challenge: Without proper organization, your application can quickly become a tangled mess

In this guide, we'll explore several approaches to organizing Flask applications, from simple to more complex architectures.

Basic Flask Application Structure​

Let's start with a simple but well-organized Flask application structure:

my_flask_app/
├── app.py # Application entry point
├── config.py # Configuration settings
├── requirements.txt # Project dependencies
├── static/ # CSS, JS, images
│ ├── css/
│ ├── js/
│ └── images/
└── templates/ # HTML templates
├── base.html
└── index.html

Here's how a basic app.py might look:

python
from flask import Flask, render_template

app = Flask(__name__)

# Load configuration
app.config.from_object('config')

@app.route('/')
def index():
return render_template('index.html', title='Home')

if __name__ == '__main__':
app.run(debug=app.config['DEBUG'])

And a simple config.py:

python
# Configuration settings
DEBUG = True
SECRET_KEY = 'your-secret-key'

This structure works well for small applications with just a few routes, but it will become unwieldy as your application grows.

Scaling Up: Application Factory Pattern​

As your application grows, you'll want to organize it better. The application factory pattern is a popular approach in Flask:

my_flask_app/
├── app/
│ ├── __init__.py # Application factory
│ ├── models/ # Database models
│ ├── routes/ # Route definitions
│ ├── static/ # Static files
│ └── templates/ # Templates
├── config.py # Configuration
├── requirements.txt # Dependencies
└── run.py # Application entry point

Here's how the application factory pattern works:

1. Application Factory (app/__init__.py):​

python
from flask import Flask

def create_app(config_name='default'):
app = Flask(__name__)

# Load config
from config import config_dict
app.config.from_object(config_dict[config_name])

# Register blueprints
from app.routes.main import main_bp
app.register_blueprint(main_bp)

return app

2. Configuration (config.py):​

python
class Config:
SECRET_KEY = 'base-secret-key'

class DevelopmentConfig(Config):
DEBUG = True

class ProductionConfig(Config):
DEBUG = False

config_dict = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}

3. Routes using Blueprints (app/routes/main.py):​

python
from flask import Blueprint, render_template

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def index():
return render_template('index.html', title='Home')

@main_bp.route('/about')
def about():
return render_template('about.html', title='About')

4. Entry Point (run.py):​

python
from app import create_app

app = create_app('development')

if __name__ == '__main__':
app.run()

This approach has several advantages:

  • Separation of concerns
  • Easy testing (you can create different app instances with different configs)
  • Cleaner organization with blueprints for different sections of your app

Blueprints: Modular Applications​

Blueprints are one of Flask's most powerful features for code organization. They allow you to divide your application into distinct components:

Example of Blueprint Structure:​

my_flask_app/
├── app/
│ ├── __init__.py
│ ├── auth/ # Authentication blueprint
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ ├── models.py
│ │ ├── routes.py
│ │ └── templates/
│ │ └── auth/
│ │ ├── login.html
│ │ └── register.html
│ ├── main/ # Main blueprint
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── templates/
│ │ └── main/
│ │ ├── index.html
│ │ └── about.html
│ ├── static/
│ └── templates/
│ └── base.html
├── config.py
└── run.py

Here's how to implement a blueprint:

Auth Blueprint (app/auth/__init__.py):​

python
from flask import Blueprint

auth_bp = Blueprint('auth', __name__, template_folder='templates')

from . import routes # Import routes at the end to avoid circular imports

Auth Routes (app/auth/routes.py):​

python
from flask import render_template, redirect, url_for
from . import auth_bp

@auth_bp.route('/login')
def login():
return render_template('auth/login.html', title='Login')

@auth_bp.route('/register')
def register():
return render_template('auth/register.html', title='Register')

Register the Blueprint (app/__init__.py):​

python
def create_app(config_name='default'):
app = Flask(__name__)

# Load config
from config import config_dict
app.config.from_object(config_dict[config_name])

# Register blueprints
from app.main import main_bp
from app.auth import auth_bp

app.register_blueprint(main_bp)
app.register_blueprint(auth_bp, url_prefix='/auth')

return app

Blueprints give you these benefits:

  • Modular code organization by feature or functionality
  • Isolated templates and static files
  • URL prefixing (like /auth/login in the example)
  • Easy to maintain and extend

Advanced: Feature-Based Structure​

For larger applications, consider organizing by feature rather than by type:

my_flask_app/
├── app/
│ ├── __init__.py
│ ├── extensions.py # Flask extensions
│ ├── features/
│ │ ├── auth/ # Authentication feature
│ │ │ ├── __init__.py
│ │ │ ├── forms.py
│ │ │ ├── models.py
│ │ │ ├── routes.py
│ │ │ ├── static/
│ │ │ └── templates/
│ │ ├── blog/ # Blog feature
│ │ │ ├── __init__.py
│ │ │ ├── forms.py
│ │ │ ├── models.py
│ │ │ ├── routes.py
│ │ │ ├── static/
│ │ │ └── templates/
│ │ └── home/ # Home pages feature
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── templates/
│ ├── static/ # Shared static files
│ └── templates/ # Shared templates
├── config.py
├── requirements.txt
└── run.py

This structure scales well for large applications with multiple developers, as each feature can be developed and maintained independently.

Real-World Example: A Blog Application​

Let's put everything together with a more comprehensive example of a simple blog application:

Application Structure:​

flask_blog/
├── app/
│ ├── __init__.py
│ ├── extensions.py
│ ├── models/
│ │ ├── __init__.py
│ │ ├── post.py
│ │ └── user.py
│ ├── auth/
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ ├── routes.py
│ │ └── templates/
│ │ └── auth/
│ │ ├── login.html
│ │ └── register.html
│ ├── blog/
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ ├── routes.py
│ │ └── templates/
│ │ └── blog/
│ │ ├── create.html
│ │ ├── edit.html
│ │ └── post.html
│ ├── main/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── templates/
│ │ └── main/
│ │ ├── index.html
│ │ └── about.html
│ ├── static/
│ └── templates/
│ └── base.html
├── config.py
├── requirements.txt
└── run.py

Extensions (app/extensions.py):​

python
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate

# Initialize extensions
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()

def init_extensions(app):
# Initialize extensions with the app
db.init_app(app)
login_manager.init_app(app)
migrate.init_app(app, db)

login_manager.login_view = 'auth.login'

App Factory (app/__init__.py):​

python
from flask import Flask

def create_app(config_name='default'):
app = Flask(__name__)

# Load config
from config import config_dict
app.config.from_object(config_dict[config_name])

# Initialize extensions
from app.extensions import init_extensions
init_extensions(app)

# Register blueprints
from app.main import main_bp
from app.auth import auth_bp
from app.blog import blog_bp

app.register_blueprint(main_bp)
app.register_blueprint(auth_bp, url_prefix='/auth')
app.register_blueprint(blog_bp, url_prefix='/blog')

return app

This structure provides a solid foundation for a Flask application that can scale as requirements grow.

Best Practices for Flask Code Organization​

Regardless of the structure you choose, follow these best practices:

  1. Use Blueprints: Even for small applications, blueprints help organize code logically
  2. Separate Configuration: Keep configuration out of your application code
  3. Use Application Factory: Makes testing easier and avoids global state issues
  4. Keep Models Separate: Maintain clear separation between data models and views
  5. Don't Import Views at Module Level: Import views inside functions to avoid circular imports
  6. Follow Python Conventions: Use PEP 8 and consistent naming throughout your project
  7. Organize Templates: Structure templates to match your blueprint organization

Summary​

Proper code organization is crucial for sustainable Flask application development. As your application grows, the right structure will help you maintain code quality and developer productivity.

Here's what we covered:

  • Basic Flask application structure
  • Application factory pattern
  • Using blueprints for modularity
  • Feature-based organization for larger applications
  • Real-world example of a blog application

Remember, there's no one-size-fits-all approach. Choose the structure that makes sense for your project's scale and complexity. Start simple and refactor as needed.

Additional Resources​

Exercises​

  1. Convert a simple Flask application to use the application factory pattern
  2. Restructure an existing project to use blueprints
  3. Create a Flask project with at least three blueprints: auth, main, and an API
  4. Implement a feature-based structure for a medium-sized Flask application
  5. Create a Flask extension and integrate it into your application


If you spot any mistakes on this website, please let me know at feedback@compilenrun.com. I’d greatly appreciate your feedback! :)