# Flask Task Manager REST API
A production-ready Flask REST API boilerplate for managing tasks with SQLite, SQLAlchemy, and input validation.
## Project Structure
```
task_manager/
├── app/
│ ├── __init__.py # App factory
│ ├── extensions.py # Flask extensions (db)
│ ├── models.py # SQLAlchemy models
│ ├── schemas.py # Input validation schemas
│ ├── errors.py # Error handlers
│ └── routes/
│ ├── __init__.py
│ └── tasks.py # Task blueprint with CRUD endpoints
├── config.py # Configuration classes
├── .env.example # Example environment variables
├── requirements.txt # Python dependencies
└── run.py # Application entry point
```
---
### `requirements.txt`
```txt
Flask==3.0.3
Flask-SQLAlchemy==3.1.1
python-dotenv==1.0.1
marshmallow==3.21.3
```
---
### `config.py`
```python
"""
Configuration module.
Loads settings from environment variables with sensible defaults.
"""
import os
from dotenv import load_dotenv
# Load variables from .env file into os.environ
load_dotenv()
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
class Config:
"""Base configuration shared across environments."""
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-change-me")
# Default to a local SQLite file if DATABASE_URL isn't set
SQLALCHEMY_DATABASE_URI = os.getenv(
"DATABASE_URL", f"sqlite:///{os.path.join(BASE_DIR, 'tasks.db')}"
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
JSON_SORT_KEYS = False
class DevelopmentConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
# Map string keys to config classes for easy lookup
config_by_name = {
"development": DevelopmentConfig,
"production": ProductionConfig,
"testing": TestingConfig,
}
```
---
### `.env.example`
```env
# Copy this file to `.env` and adjust as needed
FLASK_ENV=development
SECRET_KEY=replace-with-a-secure-random-string
DATABASE_URL=sqlite:///tasks.db
```
---
### `app/extensions.py`
```python
"""
Centralized Flask extension instances.
Keeping them here prevents circular imports in the factory/blueprints.
"""
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
```
---
### `app/models.py`
```python
"""
SQLAlchemy models.
"""
from datetime import datetime
from .extensions import db
class Task(db.Model):
"""Represents a single task in the task manager."""
__tablename__ = "tasks"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
description = db.Column(db.Text, nullable=True)
completed = db.Column(db.Boolean, default=False, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
updated_at = db.Column(
db.DateTime,
default=datetime.utcnow,
onupdate=datetime.utcnow,
nullable=False,
)
def to_dict(self):
"""Serialize the model to a JSON-friendly dict."""
return {
"id": self.id,
"title": self.title,
"description": self.description,
"completed": self.completed,
"created_at": self.created_at.isoformat(),
"updated_at": self.updated_at.isoformat(),
}
def __repr__(self):
return f"<Task {self.id}: {self.title}>"
```
---
### `app/schemas.py`
```python
"""
Marshmallow schemas for input validation.
These protect the API from malformed or malicious payloads.
"""
from marshmallow import Schema, fields, validate
class TaskCreateSchema(Schema):
"""Schema for creating a new task - title is required."""
title = fields.String(
required=True,
validate=validate.Length(min=1, max=120, error="Title must be 1-120 chars."),
)
description = fields.String(
load_default=None,
validate=validate.Length(max=2000),
allow_none=True,
)
completed = fields.Boolean(load_default=False)
class TaskUpdateSchema(Schema):
"""Schema for updating a task - all fields optional (PATCH-style)."""
title = fields.String(
validate=validate.Length(min=1, max=120, error="Title must be 1-120 chars.")
)
description = fields.String(
validate=validate.Length(max=2000),
allow_none=True,
)
completed = fields.Boolean()
```
---
### `app/errors.py`
```python
"""
Global JSON error handlers.
Ensures all errors return consistent JSON responses instead of HTML.
"""
from flask import jsonify
from marshmallow import ValidationError
from werkzeug.exceptions import HTTPException
def register_error_handlers(app):
"""Attach error handlers to the Flask app."""
@app.errorhandler(ValidationError)
def handle_validation_error(err):
# Marshmallow raises this when payload fails validation
return jsonify({"error": "Validation failed", "messages": err.messages}), 400
@app.errorhandler(404)
def handle_not_found(err):
return jsonify({"error": "Res
Generate Flask API Boilerplate Code with AI
Tested prompts for ai generate flask app compared across 5 leading AI models.
If you searched 'ai generate flask app', you are probably staring at a blank file and need a working Flask API skeleton in the next few minutes, not the next few hours. You know Python, you know what your API needs to do, and you just want the boilerplate out of the way so you can focus on actual logic. That is exactly what AI code generation is built for.
Flask boilerplate is highly repetitive: app factory pattern, blueprint registration, error handlers, config classes, database initialization, JWT or API key middleware. Writing it from scratch every project wastes time and introduces inconsistency. AI models like GPT-4, Claude, and Gemini can produce a complete, runnable Flask project structure from a single detailed prompt in under ten seconds.
This page shows you the exact prompt structure that produces the best output, compares how four leading models handle it, and explains where AI-generated Flask code is solid versus where you need to verify it yourself before shipping. If you paste the prompt below into any capable model, you will have a working Flask app skeleton ready to extend.
When to use this
AI Flask generation is the right move when you need a production-shaped skeleton fast and the architecture is well-understood. REST APIs, internal tooling backends, microservices, and prototype APIs all fit. If you can describe the endpoints and data model in a paragraph, the AI can scaffold it cleanly.
- Starting a new REST API and want a consistent project structure with blueprints, config, and error handling already wired up
- Building a quick internal tool or admin API where you need CRUD endpoints over a single database model
- Prototyping a startup MVP backend where speed to first working endpoint matters more than custom architecture
- Scaffolding a microservice that needs JWT auth, a health-check route, and a predictable folder layout
- Onboarding a new team member who needs a reference implementation of your standard Flask patterns
When this format breaks down
- Your app has non-standard architecture requirements like async-first design, complex multi-tenant data isolation, or deeply nested blueprint hierarchies. AI output defaults to the common pattern and refactoring away from it costs more than writing it directly.
- You are generating code for a security-sensitive context like payment processing or healthcare data without a thorough manual review. AI models produce plausible-looking auth and validation code that can have subtle logical flaws.
- The project already has an established codebase with strong conventions. Dropping AI-generated scaffolding into an existing app usually creates style conflicts and duplicate abstractions.
- You need a specific Flask extension combination the model has limited training data on, such as a niche third-party plugin or a very recent library version. The generated imports and configuration will likely be outdated or incorrect.
The prompt we tested
You are an expert Python developer specializing in building production-ready Flask APIs. Generate complete, runnable Flask application boilerplate code based on the user's requirements below. Follow these instructions strictly: Output a complete Flask app with a modular structure (app factory pattern, blueprints for routes, separate config.py, and requirements.txt). Include working CRUD endpoints matching the user's domain, proper error handling with JSON responses, and environment variable support via python-dotenv. Format code in labeled Markdown code blocks per file, and finish with a short 'How to Run' section listing install and launch commands. User requirements: I need a Flask REST API for a simple task manager. It should support creating, reading, updating, and deleting tasks with fields like title, description, and completed status. Use SQLite with SQLAlchemy and include basic input validation. Return the full project structure and all necessary code files (app.py, requirements.txt, config, routes, models, etc.) with clear file headers, inline comments explaining key sections, and setup/run instructions at the end.
Model comparison
| Model | Quality | Cost | Latency | Tokens |
|---|---|---|---|---|
| Claude Opus 4.7 | 6 | $0.1589 | 18.7s | 356 / 2048 |
| Claude Haiku 4.5 | 7 | $0.0105 | 11.3s | 240 / 2048 |
| GPT-5.4 | 8 | $0.0313 | 25.1s | 213 / 2048 |
| Gemini 2.5 Pro | 2 | $0.0016 | 18.4s | 219 / 259 |
| Grok 4.1 Fast Reasoning | 7 | $0.0008 | 28.2s | 362 / 1459 |
Outputs
# Flask Task Manager API - Complete Boilerplate
I'll generate a production-ready Flask REST API for task management with a modular structure. Here's the complete project:
## Project Structure
```
task-manager-api/
├── app.py
├── config.py
├── requirements.txt
├── .env.example
├── .gitignore
├── models/
│ ├── __init__.py
│ └── task.py
├── routes/
│ ├── __init__.py
│ └── tasks.py
├── schemas/
│ ├── __init__.py
│ └── task_schema.py
├── utils/
│ ├── __init__.py
│ ├── validators.py
│ └── responses.py
└── instance/
└── (auto-created)
```
---
## File: `requirements.txt`
```txt
Flask==3.0.0
Flask-SQLAlchemy==3.1.1
python-dotenv==1.0.0
Werkzeug==3.0.1
```
---
## File: `.env.example`
```env
# Flask Configuration
FLASK_ENV=development
FLASK_APP=app.py
SECRET_KEY=your-secret-key-here-change-in-production
# Database
DATABASE_URL=sqlite:///instance/tasks.db
# Server
DEBUG=True
PORT=5000
HOST=0.0.0.0
```
---
## File: `.gitignore`
```
# Environment variables
.env
.env.local
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Database
instance/
*.db
*.sqlite
*.sqlite3
# OS
.DS_Store
Thumbs.db
```
---
## File: `config.py`
```python
"""
Flask application configuration module.
Handles environment-based settings and database configuration.
"""
import os
from dotenv import load_dotenv
from datetime import timedelta
# Load environment variables from .env file
load_dotenv()
class Config:
"""Base configuration with common settings."""
# Flask settings
SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
FLASK_ENV = os.getenv('FLASK_ENV', 'development')
# SQLAlchemy settings
SQLALCHEMY_DATABASE_URI = os.getenv(
'DATABASE_URL',
'sqlite:///instance/tasks.db'
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
# API settings
JSON_SORT_KEYS = False
JSONIFY_PRETTYPRINT_REGULAR = True
# Pagination
ITEMS_PER_PAGE = 20
# Request timeout
PROPAGATE_EXCEPTIONS = True
class DevelopmentConfig(Config):
"""Development configuration with debug mode enabled."""
DEBUG = True
TESTING = False
SQLALCHEMY_ECHO = True
class TestingConfig(Config):
"""Testing configuration with SQLite in-memory database."""
DEBUG = True
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(Config):
"""Production configuration with strict settings."""
DEBUG = False
TESTING = False
SQLALCHEMY_ECHO = False
# Configuration dictionary
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig,
}
def get_config():
"""Get appropriate config based on FLASK_ENV."""
env = os.getenv('FLASK_ENV', 'development')
return config.get(env, config['default'])
```
---
## File: `models/__init__.py`
```python
"""
Models package - SQLAlchemy ORM models for database entities.
"""
from flask_sqlalchemy import SQLAlchemy
# Initialize SQLAlchemy without app binding
db = SQLAlchemy()
# Import models to register them
from models.task import Task
__all__ = ['db', 'Task']
```
---
## File: `models/task.py`
```python
"""
Task model - ORM definition for task entities.
Defines the database schema and methods for task management.
"""
from datetime import datetime
from models import db
class Task(db.Model):
"""
Task model representing a task entity in the database.
Attributes:
id (int): Primary key, auto-incremented.
title (str): Task title, required, max 200 characters.
description (str): Detailed task description, optional.
completed (bool): Task completion status, defaults to False.
created_at (datetime): Timestamp of task creation.
updated_at (datetime): Timestamp of last update.
"""
__tablename__ = 'tasks'
# Primary Key
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# Task Data
title = db.Column(db.String(200), nullable=False, index=True)
description = db.Column(db.Text, nullable=True)
completed = db.Column(db.Boolean, default=False, nullable=False)
# Timestamps
created_at = db.Column(
db.DateTime,
nullable=False,
default=datetime.utcnow,
index=True
)
updated_at = db.Column(
db.DateTime,
nullable=False,
default=datetime.utcnow,
onupdate=datetime.utcnow
)
def __repr__(self):
"""String representation of Task object."""
return f'<Task {self.id}: {self.title}>'
def to_dict(self):
"""
Convert Task object to dictionary for JSON serialization.
Returns:
dict: Task data with all fields.
"""
return {
'id': self.id,
'title': self.title,
'description': self.description,
'completed': self.completed,
'created_at': self.created_at.isoformat(),
'updated_at': self.updated_at.isoformat(),
}
@staticmethod
def from_dict(data):
"""
Create Task object from dictionary.
Args:
data (dict): Dictionary containing task fields.
Returns:
Task: New Task instance.
"""
return Task(
title=data.get('title'),
description=data.get('description', ''),
completed=data.get('completed', False),
)
```
---
## File: `schemas/__init__.py`
```python
"""
Schemas package - Request/response validation and serialization.
"""
```
---
## File: `schemas/task_schema.py`
```python
"""
Task schema - Validation schemas for task request/response data.
Handles input validation and serialization of task objects.
"""
class TaskSchema:
"""Schema for validating task input data."""
@staticmethod
def validate_create(data):
"""
Validate data for task creation.
Args:
data (dict): Request data to validate.
Returns:
tuple: (is_valid, errors_dict)
Raises:
ValueError: If required fields are missing or invalid.
"""
errors = {}
# Validate title
if 'title' not in data or not data['title']:
errors['title'] = 'Title is required and cannot be empty.'
elif not isinstance(data['title'], str):
errors['title'] = 'Title must be a string.'
elif len(data['title']) > 200:
errors['title'] = 'Title must not exceed 200 characters.'
## Project Structure
```text
task_manager_api/
├── app.py
├── requirements.txt
├── .env
├── config.py
└── app/
├── __init__.py
├── extensions.py
├── models/
│ ├── __init__.py
│ └── task.py
├── routes/
│ ├── __init__.py
│ └── tasks.py
└── utils/
├── __init__.py
└── errors.py
```
---
## `requirements.txt`
```txt
Flask==3.0.3
Flask-SQLAlchemy==3.1.1
python-dotenv==1.0.1
```
---
## `.env`
```env
# Flask environment settings
FLASK_ENV=development
FLASK_DEBUG=True
# SQLite database path
DATABASE_URL=sqlite:///tasks.db
```
---
## `config.py`
```python
import os
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
class Config:
"""Base configuration class."""
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key")
SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", "sqlite:///tasks.db")
SQLALCHEMY_TRACK_MODIFICATIONS = False
JSON_SORT_KEYS = False
```
---
## `app.py`
```python
from app import create_app
# Create the Flask application using the factory pattern
app = create_app()
if __name__ == "__main__":
app.run()
```
---
## `app/__init__.py`
```python
from flask import Flask, jsonify
from config import Config
from app.extensions import db
from app.routes.tasks import tasks_bp
from app.utils.errors import register_error_handlers
def create_app(config_class=Config):
"""Application factory function."""
app = Flask(__name__)
app.config.from_object(config_class)
# Initialize extensions
db.init_app(app)
# Register blueprints
app.register_blueprint(tasks_bp, url_prefix="/api/tasks")
# Register global error handlers
register_error_handlers(app)
# Create database tables automatically on startup
with app.app_context():
db.create_all()
@app.route("/")
def health_check():
return jsonify({
"message": "Task Manager API is running",
"status": "success"
}), 200
return app
```
---
## `app/extensions.py`
```python
from flask_sqlalchemy import SQLAlchemy
# Initialize extensions here so they can be imported elsewhere
db = SQLAlchemy()
```
---
## `app/models/__init__.py`
```python
from app.models.task import Task
__all__ = ["Task"]
```
---
## `app/models/task.py`
```python
from app.extensions import db
class Task(db.Model):
"""Task model representing a task in the database."""
__tablename__ = "tasks"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255), nullable=False)
description = db.Column(db.Text, nullable=True)
completed = db.Column(db.Boolean, default=False, nullable=False)
def to_dict(self):
"""Serialize the model to a Python dictionary."""
return {
"id": self.id,
"title": self.title,
"description": self.description,
"completed": self.completed,
}
```
---
## `app/routes/__init__.py`
```python
# This file can remain empty or be used for route package exports.
```
---
## `app/routes/tasks.py`
```python
from flask import Blueprint, jsonify, request
from app.extensions import db
from app.models.task import Task
tasks_bp = Blueprint("tasks", __name__)
def validate_task_input(data, partial=False):
"""
Validate incoming task payload.
If partial=True, used for updates where all fields are optional.
"""
errors = {}
if not data:
errors["body"] = "Request body must be valid JSON."
if not partial or "title" in data:
title = data.get("title")
if title is None or not isinstance(title, str) or not title.strip():
errors["title"] = "Title is required and must be a non-empty string."
if "description" in data and data.get("description") is not None:
if not isinstance(data.get("description"), str):
errors["description"] = "Description must be a string."
if "completed" in data and not isinstance(data.get("completed"), bool):
errors["completed"] = "Completed must be a boolean."
return errors
@tasks_bp.route("/", methods=["POST"])
def create_task():
"""Create a new task."""
data = request.get_json(silent=True)
errors = validate_task_input(data)
if errors:
return jsonify({
"status": "error",
"message": "Validation failed",
"errors": errors
}), 400
task = Task(
title=data["title"].strip(),
description=data.get("description", ""),
completed=data.get("completed", False)
)
db.session.add(task)
db.session.commit()
return jsonify({
"status": "success",
"message": "Task created successfully",
"data": task.to_dict()
}), 201
@tasks_bp.route("/", methods=["GET"])
def get_tasks():
"""Get all tasks."""
tasks = Task.query.all()
return jsonify({
"status": "success",
"data": [task.to_dict() for task in tasks]
}), 200
@tasks_bp.route("/<int:task_id>", methods=["GET"])
def get_task(task_id):
"""Get a single task by ID."""
task = Task.query.get(task_id)
if not task:
return jsonify({
"status": "error",
"message": f"Task with id {task_id} not found"
}), 404
return jsonify({
"status": "success",
"data": task.to_dict()
}), 200
@tasks_bp.route("/<int:task_id>", methods=["PUT"])
def update_task(task_id):
"""Update an existing task."""
task = Task.query.get(task_id)
if not task:
return jsonify({
"status": "error",
"message": f"Task with id {task_id} not found"
}), 404
data = request.get_json(silent=True)
errors = validate_task_input(data, partial=True)
if errors:
return jsonify({
"status": "error",
"message": "Validation failed",
"errors": errors
}), 400
# Update only provided fields
if "title" in data:
task.title = data["title"].strip()
if "description" in data:
task.description = data["description"]
if "completed" in data:
task.completed = data["completed"]
db.session.commit()
return jsonify({
"status": "success",
"message": "Task updated successfully",
"data": task.to_dict()
}), 200
@tasks_bp.route("/<int:task_id>", methods=["DELETE"])
def delete_task(task_id):
"""Delete a task by ID."""
task = Task.query.get(task_id)
if not task:
return jsonify({
"status": "error",
"message": f"Task with id {task_id} not found"
}), 404
db.session.delete(task)
db.session.commit()
return jsonify({
"status": "success",
"message": "Task deleted successfully"
}), 200
```
---
## `app/utils/__init__.py`
```python
# Utility package initializer
```
---
## `app/utils/errors.py`
```python
from flask import jsonify
from werkzeug.exceptions import HTTPException
def register_error_handlers(app):
"""Register application-wide JSON error handlers."""
@app.errorhandler(404)
def not_found(error):
return jsonify({
"status": "error",
"message": "Resource not found"
}), 404
@app.errorhandler(405)
def method_not_allowed(error):
return jsonify({
"status": "error",
"message": "Method not allowed"
}), 405
@app.errorhandler(400)
def bad_request(error):
return jsonify({
"status": "error",
"message": "Bad request"
}), 400
@app.errorhandler(HTTPException)
def handle_http_exception(error):
return jsonify({
"status": "error",
"message": error.description
}), error.code
@app.errorhandler(Exception)
def handle_unexpected_error(error):
return jsonify({
"status": "error",
"message": "An unexpected error occurred"
}), 500
```
---
## How to Run
### 1. Create the project files
Create the folder structure above and save each file in its matching path.
### 2. Install dependencies
```bash
pip install -r requirements.txt
```
### 3. Run the Flask app
```bash
python app.py
```
### 4. API Base URL
```text
http://127.0.0.1:5000/api/tasks
```
### Example Endpoints
- `POST /api/tasks/` — create a task
- `GET /api/tasks/` — list all tasks
- `GET /api/tasks/<id>` — get one task
- `PUT /api/tasks/<id>` — update
Of course. As a Flask expert, I will generate a complete, production-ready boilerplate for a Task Manager REST API. The code follows modern best practices, including the application factory pattern, blueprints for modular routing, SQLAlchemy for database interaction, and environment-based configuration. Here is the complete project structure and code. ### Project Structure ``` task_manager_api/ ├── app/ │ ├── __init__.py # Contains the application factory │ ├── models.py # Defines the SQLAlchemy DB models │ └── routes/ │ ├── __init__.py # Makes 'routes' a Python package │ └── task_routes.py # Blueprint with all task-related API endpoints ├── instance/ │ └── (tasks.db will be created here automatically) ├── .env.example # Example environment variables ├── .flaskenv # Instructs the 'flask' command-line tool ├── config.py # Application configuration settings ├── requirements.txt # Project dependencies └── run.py # Main entry point for running the application ``` --- ### File Contents #### 1. `requirements.txt` This file lists all the Python packages required for the
```python
# app.py
"""
Flask app factory for the Task Manager API.
Handles app creation, extension initialization, blueprint registration, and error handling.
"""
from flask import Flask, jsonify
from dotenv import load_dotenv
from config import DevelopmentConfig
from extensions import db
from tasks import tasks_bp
def create_app(config_class=DevelopmentConfig):
# Load environment variables from .env file
load_dotenv()
# Create Flask app and load config
app = Flask(__name__)
app.config.from_object(config_class)
# Initialize extensions
db.init_app(app)
# Create database tables only in debug/development mode
if app.config.get('DEBUG', False):
with app.app_context():
db.create_all()
# Register blueprints
app.register_blueprint(tasks_bp, url_prefix='/api')
# Global error handlers for JSON responses
@app.errorhandler(404)
def not_found(e):
return jsonify({'error': 'Resource not found'}), 404
@app.errorhandler(400)
def bad_request(e):
return jsonify({'error': 'Bad request parameters'}), 400
@app.errorhandler(500)
def internal_error(e):
db.session.rollback()
return jsonify({'error': 'Internal server error'}), 500
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
```
```python
# config.py
"""
Configuration classes for different environments.
Supports environment variables via python-dotenv.
"""
import os
class Config:
"""Base configuration."""
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-task-manager-key-change-in-prod'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
"""Development configuration."""
DEBUG = True
class ProductionConfig(Config):
"""Production configuration."""
DEBUG = False
```
```python
# extensions.py
"""
Flask extensions initialization.
"""
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
```
```python
# models.py
"""
SQLAlchemy models for the Task Manager.
Defines the Task model with to_dict() for JSON serialization.
"""
from extensions import db
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), index=True, nullable=False)
description = db.Column(db.Text, nullable=True)
completed = db.Column(db.Boolean, default=False)
def to_dict(self):
"""Convert model to dictionary for JSON response."""
return {
'id': self.id,
'title': self.title,
'description': self.description,
'completed': self.completed
}
```
```python
# tasks.py
"""
Blueprint for task-related routes.
Implements CRUD operations with basic input validation and error handling.
"""
from flask import Blueprint, request, jsonify
from extensions import db
from models import Task
tasks_bp = Blueprint('tasks', __name__)
@tasks_bp.route('/tasks', methods=['GET'])
def get_tasks():
"""Retrieve all tasks."""
tasks = Task.query.all()
return jsonify({'tasks': [task.to_dict() for task in tasks]})
@tasks_bp.route('/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
"""Retrieve a single task by ID."""
task = Task.query.get_or_404(task_id)
return jsonify(task.to_dict())
@tasks_bp.route('/tasks', methods=['POST'])
def create_task():
"""Create a new task with basic validation."""
data = request.get_json() or {}
# Basic input validation
if not data.get('title'):
return jsonify({'error': 'Title is required'}), 400
if not isinstance(data.get('title'), str) or not 1 <= len(data['title']) <= 100:
return jsonify({'error': 'Title must be a string between 1 and 100 characters'}), 400
if data.get('description') is not None and not isinstance(data['description'], str):
return jsonify({'error': 'Description must be a string or null'}), 400
if data.get('completed') is not None and not isinstance(data['completed'], bool):
return jsonify({'error': 'Completed must be a boolean'}), 400
task = Task(
title=data['title'],
description=data.get('description'),
completed=data.get('completed', False)
)
db.session.add(task)
db.session.commit()
return jsonify(task.to_dict()), 201
@tasks_bp.route('/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
"""Update an existing task with basic validation."""
task = Task.query.get_or_404(task_id)
data = request.get_json() or {}
# Basic input validation for provided fields
if data.get('title') is not None:
if not isinstance(data['title'], str) or not 1 <= len(data['title']) <= 100:
return jsonify({'error': 'Title must be a string between 1 and 100 characters'}), 400
task.title = data['title']
if data.get('description') is not None:
if data['description'] is not None and not isinstance(data['description'], str):
return jsonify({'error': 'Description must be a string or null'}), 400
task.description = data['description']
if data.get('completed') is not None:
if not isinstance(data['completed'], bool):
return jsonify({'error': 'Completed must be a boolean'}), 400
task.completed = data['completed']
db.session.commit()
return jsonify(task.to_dict())
@tasks_bp.route('/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
"""Delete a task by ID."""
task = Task.query.get_or_404(task_id)
db.session.delete(task)
db.session.commit()
return '', 204
```
```txt
# requirements.txt
Flask==3.0.3
Flask-SQLAlchemy==3.1.1
python-dotenv==1.0.1
```
```env
# .env.example
# Copy this to .env and customize as needed.
FLASK_ENV=development
SECRET_KEY=your-secret-key-here
DATABASE_URL=sqlite:///app.db
```
## How to Run
1. Create a project directory and save all files above into it.
2. Copy `.env.example` to `.env` (optional, defaults work).
3. Install dependencies: `pip install -r requirements.txt`
4. Launch the app: `python app.py`
5. The API will be available at `http://localhost:5000/api/tasks`
- Test with tools like curl or Postman (e.g., `curl http://localhost:5000/api/tasks`)
What makes these work
-
01Specify extensions by name
Saying 'add authentication' gets you a random choice of flask-login, flask-jwt-extended, or hand-rolled token logic. Saying 'use flask-jwt-extended with refresh tokens' gets you exactly what you need. Name every library you want in the prompt and the model will wire them together correctly instead of guessing.
-
02Request the folder structure explicitly
Ask the model to output the folder tree first, then each file. This forces it to commit to a consistent layout before writing code, which dramatically reduces cases where imports reference paths that do not match the actual file locations it generates. A one-line 'show the project tree before the code' instruction pays off every time.
-
03Pin your Python and library versions
Flask 2.x and Flask 3.x have meaningful differences, and SQLAlchemy 1.4 versus 2.0 syntax diverges significantly. Include 'Python 3.11, Flask 3.0, SQLAlchemy 2.0' in your prompt and the model will use the current API instead of defaulting to older patterns it saw more of in training data.
-
04Ask for a requirements.txt in the same output
Generated code that imports a library you do not have installed wastes time. Ending your prompt with 'include a requirements.txt with pinned versions' gives you a runnable environment instantly. Verify the pins against PyPI before committing, since models sometimes hallucinate version numbers for minor releases.
More example scenarios
Generate a Flask REST API boilerplate for a SaaS product. Include an app factory in __init__.py, a config.py with Development and Production classes, a users blueprint with register and login endpoints, JWT authentication using flask-jwt-extended, SQLAlchemy with a User model, and a global error handler returning JSON errors. Use Python 3.11.
A complete project tree with app/__init__.py (create_app factory), app/config.py (two config classes), app/models/user.py (User with hashed password), app/blueprints/auth/routes.py (POST /register and POST /login returning access tokens), extensions.py initializing db and jwt, and a requirements.txt pinning all dependencies.
Generate a minimal Flask API for an internal data science tool. Two endpoints: POST /predict that accepts a JSON body with a 'features' list and returns a 'prediction' value, and GET /health. Include input validation with marshmallow, structured JSON logging, and a stub model loader in a separate module. No database needed.
app.py with Flask app, a schemas.py defining PredictRequestSchema with marshmallow, a model_loader.py stub that loads a pickle file path from an env variable, route handlers with validation errors returned as 400 JSON, and Python logging configured to emit JSON-formatted lines to stdout.
Scaffold a Flask microservice for order management. Include blueprints for orders and products, SQLAlchemy models for Order and Product with a many-to-many relationship, pagination on GET /orders, an API key middleware that checks an X-API-Key header against an env variable, and Flask-Migrate for database migrations.
Project with blueprints/orders/routes.py and blueprints/products/routes.py, models defining the association table, a before_request hook enforcing API key auth on all routes, paginated query using SQLAlchemy paginate(), a migrations/ folder initialized via Flask-Migrate, and a README with setup commands.
Generate a Flask app that receives GitHub webhook POST requests. Validate the X-Hub-Signature-256 header against a secret from environment variables. Parse the JSON payload, log the event type and repository name, and push the event to a Redis list using redis-py. Return 200 on success and 403 on invalid signature.
Single-file Flask app with a /webhook POST route, HMAC SHA-256 signature validation logic, redis.Redis client initialized from REDIS_URL env var, lpush call to a configurable list name, correct 403 response on signature mismatch, and inline comments explaining each validation step.
Create a Flask API that accepts PDF file uploads via POST /upload, validates file type and size under 10MB, saves the file to a local uploads/ directory with a UUID filename, stores metadata in a SQLite database with SQLAlchemy, and returns a JSON response with the file ID and original filename.
Route using request.files, file extension and MIME type check, MAX_CONTENT_LENGTH config set to 10MB, uuid4-based filename generation, SQLAlchemy Upload model with id, original_filename, stored_filename, and created_at columns, and a 413 error handler for oversized files.
Common mistakes to avoid
-
Vague prompts produce generic output
Prompting 'generate a Flask app' returns a hello-world single file with no structure, which is useless as a starting point. The model needs your endpoint list, chosen extensions, and project layout style to produce anything worth keeping. Treat the prompt like a spec document, not a search query.
-
Not testing database migrations before use
AI-generated SQLAlchemy models frequently have column type mismatches or missing relationship backrefs that only surface when you run flask db migrate. Always run the migration commands and inspect the generated migration file before trusting the schema. A wrong column type in a migration is painful to fix after data exists.
-
Trusting generated secret handling
Models commonly hardcode SECRET_KEY or JWT_SECRET_KEY as string literals in config.py or even directly in the app file. This is a critical security mistake if committed to version control. Always replace any hardcoded secret with an os.environ.get() call before the code leaves your machine.
-
Ignoring error handler completeness
Generated error handlers often only cover 404 and 500. A production Flask API needs handlers for 400, 401, 403, 422, and 429 at minimum to return consistent JSON error shapes. Check the generated error handling section against your actual API contract and add the missing cases manually.
-
Skipping the CORS configuration
AI-generated Flask apps rarely include CORS headers unless you ask explicitly. If a frontend will call your API from a different origin, add 'include flask-cors with CORS configured for the allowed origins' to your prompt. Debugging CORS issues after the fact when you thought the backend was done is a common time sink.
Related queries
Frequently asked questions
Can AI generate a Flask app with a database model?
Yes. Specify SQLAlchemy or another ORM in your prompt along with the model fields and relationships you need. Models like GPT-4 and Claude will generate the model class, the database initialization in your app factory, and the migration setup if you ask for Flask-Migrate. Always review foreign key and relationship definitions manually before running migrations.
What is the best AI model for generating Flask code?
GPT-4o and Claude 3.5 Sonnet consistently produce the most complete and syntactically correct Flask boilerplate based on community testing as of mid-2025. Claude tends to produce cleaner separation of concerns across files. GPT-4o tends to produce more inline comments. Gemini 1.5 Pro is a solid free alternative but occasionally uses deprecated Flask patterns.
How do I make sure the AI-generated Flask code actually runs?
Create a fresh virtual environment, install the generated requirements.txt, and run flask run immediately after generating. Fix import errors and missing dependencies before modifying any logic. Most AI-generated Flask skeletons run on the first or second attempt if your prompt was specific. Vague prompts produce code that requires more debugging.
Can I use AI to add endpoints to an existing Flask app?
Yes, but paste your existing app structure and relevant model definitions into the prompt as context. Without that context, the model will generate code that conflicts with your existing naming conventions, config keys, and extension initialization. Providing the existing __init__.py and relevant models as context produces output that integrates cleanly.
Is AI-generated Flask code production-ready?
The structure and patterns are usually sound for production use, but the generated code should not be deployed without review. Check secret key handling, input validation completeness, SQL query safety if using raw queries, and rate limiting. The boilerplate saves setup time, but the security review is still your responsibility.
How do I generate a Flask app with REST API authentication using AI?
Name the authentication method explicitly in your prompt. For token-based auth write 'use flask-jwt-extended with access and refresh tokens'. For session auth write 'use flask-login with server-side sessions'. For simple API key auth describe the header name and lookup mechanism. Ambiguous auth requests produce inconsistent implementations that mix patterns from different approaches.
Try it with a real tool
Run this prompt in one of these tools. Affiliate links help keep Gridlyx free.