Use Case
/
Rapid Development
Automate boiler plate code creation
Model
•
Claude 3.7 Sonnet
Generate Flask boilerplate: app factory, environment configs, SQLAlchemy models, and RESTful Blueprints.
Flask Application Boilerplate
Here's a comprehensive Flask boilerplate with app factory pattern, environment configurations, SQLAlchemy models, and RESTful Blueprints.
Project Structure
1my_flask_app/
2├── app/
3│ ├── __init__.py
4│ ├── extensions.py
5│ ├── models/
6│ │ ├── __init__.py
7│ │ └── user.py
8│ ├── api/
9│ │ ├── __init__.py
10│ │ ├── resources/
11│ │ │ ├── __init__.py
12│ │ │ └── user.py
13│ │ └── routes.py
14│ └── config.py
15├── migrations/
16├── tests/
17│ ├── __init__.py
18│ ├── conftest.py
19│ └── test_api.py
20├── .env
21├── .env.example
22├── .gitignore
23├── requirements.txt
24└── wsgi.py
Configuration Files
app/config.py
1import os
2from datetime import timedelta
3
4class Config:
5 """Base configuration."""
6 SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-please-change')
7 APP_DIR = os.path.abspath(os.path.dirname(__file__))
8 PROJECT_ROOT = os.path.abspath(os.path.join(APP_DIR, os.pardir))
9 SQLALCHEMY_TRACK_MODIFICATIONS = False
10 JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY', 'jwt-secret-key')
11 JWT_ACCESS_TOKEN_EXPIRES = timedelta(hours=1)
12
13
14class DevelopmentConfig(Config):
15 """Development configuration."""
16 ENV = 'development'
17 DEBUG = True
18 SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL',
19 'sqlite:///' + os.path.join(Config.PROJECT_ROOT, 'dev.db'))
20
21
22class TestingConfig(Config):
23 """Testing configuration."""
24 ENV = 'testing'
25 TESTING = True
26 DEBUG = True
27 SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL',
28 'sqlite:///' + os.path.join(Config.PROJECT_ROOT, 'test.db'))
29
30
31class ProductionConfig(Config):
32 """Production configuration."""
33 ENV = 'production'
34 DEBUG = False
35 SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
36 SECRET_KEY = os.environ.get('SECRET_KEY')
37 JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY')
38
39
40config = {
41 'development': DevelopmentConfig,
42 'testing': TestingConfig,
43 'production': ProductionConfig,
44 'default': DevelopmentConfig
45}
.env.example
1FLASK_APP=wsgi.py
2FLASK_ENV=development
3SECRET_KEY=your-secret-key
4JWT_SECRET_KEY=your-jwt-secret-key
5DATABASE_URL=postgresql://username:password@localhost:5432/dbname
Extensions and App Factory
app/extensions.py
1from flask_sqlalchemy import SQLAlchemy
2from flask_migrate import Migrate
3from flask_jwt_extended import JWTManager
4
5db = SQLAlchemy()
6migrate = Migrate()
7jwt = JWTManager()
app/init.py
1from flask import Flask
2from .extensions import db, migrate, jwt
3from .config import config
4
5
6def create_app(config_name='default'):
7 """Application factory pattern."""
8 app = Flask(__name__)
9 app.config.from_object(config[config_name])
10
11 # Initialize extensions
12 db.init_app(app)
13 migrate.init_app(app, db)
14 jwt.init_app(app)
15
16 # Register blueprints
17 from .api import api_bp
18 app.register_blueprint(api_bp, url_prefix='/api/v1')
19
20 # Shell context for flask cli
21 @app.shell_context_processor
22 def ctx():
23 return {'app': app, 'db': db}
24
25 return app
Models
app/models/init.py
1from app.extensions import db
2
3# Import models here to ensure they are registered with SQLAlchemy
4from .user import User
app/models/user.py
1from datetime import datetime
2from werkzeug.security import generate_password_hash, check_password_hash
3from app.extensions import db
4
5
6class User(db.Model):
7 """User model for storing user related details."""
8 __tablename__ = 'users'
9
10 id = db.Column(db.Integer, primary_key=True)
11 email = db.Column(db.String(255), unique=True, nullable=False)
12 username = db.Column(db.String(50), unique=True, nullable=False)
13 password_hash = db.Column(db.String(255), nullable=False)
14 is_active = db.Column(db.Boolean, default=True)
15 created_at = db.Column(db.DateTime, default=datetime.utcnow)
16 updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
17
18 def __init__(self, username, email, password):
19 self.username = username
20 self.email = email
21 self.password = password
22
23 @property
24 def password(self):
25 raise AttributeError('password is not a readable attribute')
26
27 @password.setter
28 def password(self, password):
29 self.password_hash = generate_password_hash(password)
30
31 def verify_password(self, password):
32 return check_password_hash(self.password_hash, password)
33
34 def to_dict(self):
35 return {
36 'id': self.id,
37 'username': self.username,
38 'email': self.email,
39 'is_active': self.is_active,
40 'created_at': self.created_at.isoformat(),
41 'updated_at': self.updated_at.isoformat()
42 }
43
44 def __repr__(self):
45 return f'<User {self.username}>'
API Blueprint and Resources
app/api/init.py
1from flask import Blueprint
2
3api_bp = Blueprint('api', __name__)
4
5from .routes import *
app/api/routes.py
1from flask import jsonify
2from . import api_bp
3from .resources.user import UserResource, UserListResource, UserLoginResource
4
5# User routes
6api_bp.add_url_rule('/users', view_func=UserListResource.as_view('user_list'))
7api_bp.add_url_rule('/users/<int:user_id>', view_func=UserResource.as_view('user_detail'))
8api_bp.add_url_rule('/auth/login', view_func=UserLoginResource.as_view('user_login'))
9
10@api_bp.route('/health')
11def health_check():
12 return jsonify({"status": "healthy"})
app/api/resources/init.py
1# Import resources here
2from .user import UserResource, UserListResource, UserLoginResource
app/api/resources/user.py
1from flask import request, jsonify
2from flask.views import MethodView
3from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
4
5from app.extensions import db
6from app.models.user import User
7
8
9class UserListResource(MethodView):
10 """Resource for creating users and getting all users."""
11
12 def get(self):
13 """Get all users."""
14 users = User.query.all()
15 return jsonify([user.to_dict() for user in users]), 200
16
17 def post(self):
18 """Create a new user."""
19 data = request.get_json()
20
21 # Validate required fields
22 if not all(k in data for k in ('username', 'email', 'password')):
23 return jsonify({'message': 'Missing required fields'}), 400
24
25 # Check if user already exists
26 if User.query.filter_by(email=data['email']).first():
27 return jsonify({'message': 'User with this email already exists'}), 409
28
29 if User.query.filter_by(username=data['username']).first():
30 return jsonify({'message': 'User with this username already exists'}), 409
31
32 # Create new user
33 user = User(
34 username=data['username'],
35 email=data['email'],
36 password=data['password']
37 )
38
39 db.session.add(user)
40 db.session.commit()
41
42 return jsonify(user.to_dict()), 201
43
44
45class UserResource(MethodView):
46 """Resource for getting, updating and deleting a user."""
47
48 @jwt_required()
49 def get(self, user_id):
50 """Get a user by id."""
51 user = User.query.get_or_404(user_id)
52 return jsonify(user.to_dict()), 200
53
54 @jwt_required()
55 def put(self, user_id):
56 """Update a user."""
57 current_user_id = get_jwt_identity()
58 if current_user_id != user_id:
59 return jsonify({'message': 'Unauthorized access'}), 403
60
61 user = User.query.get_or_404(user_id)
62 data = request.get_json()
63
64 if 'username' in data:
65 user.username = data['username']
66 if 'email' in data:
67 user.email = data['email']
68 if 'password' in data:
69 user.password = data['password']
70
71 db.session.commit()
72
73 return jsonify(user.to_dict()), 200
74
75 @jwt_required()
76 def delete(self, user_id):
77 """Delete a user."""
78 current_user_id = get_jwt_identity()
79 if current_user_id != user_id:
80 return jsonify({'message': 'Unauthorized access'}), 403
81
82 user = User.query.get_or_404(user_id)
83 db.session.delete(user)
84 db.session.commit()
85
86 return jsonify({'message': 'User deleted successfully'}), 200
87
88
89class UserLoginResource(MethodView):
90 """Resource for user login."""
91
92 def post(self):
93 """Login a user."""
94 data = request.get_json()
95
96 if not all(k in data for k in ('email', 'password')):
97 return jsonify({'message': 'Missing email or password'}), 400
98
99 user = User.query.filter_by(email=data['email']).first()
100
101 if not user or not user.verify_password(data['password']):
102 return jsonify({'message': 'Invalid email or password'}), 401
103
104 access_token = create_access_token(identity=user.id)
105
106 return jsonify({
107 'access_token': access_token,
108 'user': user.to_dict()
109 }), 200
WSGI Entry Point
wsgi.py
1import os
2from app import create_app
3
4app = create_app(os.getenv('FLASK_ENV', 'default'))
5
6if __name__ == '__main__':
7 app.run(host='0.0.0.0')
Requirements File
requirements.txt
1Flask==2.2.3
2Flask-SQLAlchemy==3.0.3
3Flask-Migrate==4.0.4
4Flask-JWT-Extended==4.5.2
5psycopg2-binary==2.9.6
6python-dotenv==1.0.0
7pytest==7.3.1
Tests
tests/conftest.py
1import pytest
2from app import create_app
3from app.extensions import db
4from app.models.user import User
5
6
7@pytest.fixture
8def app():
9 app = create_app('testing')
10
11 with app.app_context():
12 db.create_all()
13 yield app
14 db.session.remove()
15 db.drop_all()
16
17
18@pytest.fixture
19def client(app):
20 return app.test_client()
21
22
23@pytest.fixture
24def db_session(app):
25 with app.app_context():
26 yield db.session
27
28
29@pytest.fixture
30def test_user(db_session):
31 user = User(
32 username='testuser',
33 email='test@example.com',
34 password='password123'
35 )
36 db_session.add(user)
37 db_session.commit()
38 return user
tests/test_api.py
1import json
2from flask_jwt_extended import create_access_token
3
4
5def test_health_check(client):
6 response = client.get('/api/v1/health')
7 assert response.status_code == 200
8 assert response.json['status'] == 'healthy'
9
10
11def test_create_user(client):
12 data = {
13 'username': 'newuser',
14 'email': 'newuser@example.com',
15 'password': 'password123'
16 }
17 response = client.post(
18 '/api/v1/users',
19 data=json.dumps(data),
20 content_type='application/json'
21 )
22 assert response.status_code == 201
23 assert response.json['username'] == 'newuser'
24 assert response.json['email'] == 'newuser@example.com'
25 assert 'password' not in response.json
26
27
28def test_get_user(client, test_user, app):
29 with app.app_context():
30 access_token = create_access_token(identity=test_user.id)
31
32 response = client.get(
33 f'/api/v1/users/{test_user.id}',
34 headers={'Authorization': f'Bearer {access_token}'}
35 )
36 assert response.status_code == 200
37 assert response.json['username'] == 'testuser'
38 assert response.json['email'] == 'test@example.com'
39
40
41def test_user_login(client, test_user):
42 data = {
43 'email': 'test@example.com',
44 'password': 'password123'
45 }
46 response = client.post(
47 '/api/v1/auth/login',
48 data=json.dumps(data),
49 content_type='application/json'
50 )
51 assert response.status_code == 200
52 assert 'access_token' in response.json
53 assert response.json['user']['username'] == 'testuser'
.gitignore
1# Python
2__pycache__/
3*.py[cod]
4*$py.class
5*.so
6.Python
7env/
8build/
9develop-eggs/
10dist/
11downloads/
12eggs/
13.eggs/
14lib/
15lib64/
16parts/
17sdist/
18var/
19*.egg-info/
20.installed.cfg
21*.egg
22
23# Flask
24instance/
25.webassets-cache
26
27# Environments
28.env
29.venv
30env/
31venv/
32ENV/
33env.bak/
34venv.bak/
35
36# Database
37*.db
38*.sqlite
39
40# IDE
41.idea/
42.vscode/
43*.swp
44*.swo
45
46# Logs
47logs/
48*.log
This boilerplate provides a solid foundation for building a Flask RESTful API with:
- Application factory pattern
- Environment-specific configurations
- SQLAlchemy ORM with User model
- RESTful API with Blueprint organization
- JWT authentication
- Basic test setup
To get started:
- Create a virtual environment:
python -m venv venv
- Activate it:
source venv/bin/activate
(Linux/Mac) orvenv\Scripts\activate
(Windows) - Install dependencies:
pip install -r requirements.txt
- Copy
.env.example
to.env
and configure your environment variables - Initialize the database:
flask db init && flask db migrate && flask db upgrade
- Run the application:
flask run
Explore Related Use Cases
Experience Ninja's AI Assistant
Try for free today. Plans starting at $5/month.