Flask has become one of the most popular Python web frameworks, and for good reason. Its simplicity, flexibility, and “micro” philosophy make it an excellent choice for developers who want control over their application architecture without the overhead of larger frameworks. Whether you’re building a quick API, a prototype, or a full-scale web application, Flask gives you the tools you need without forcing decisions on you.
What Makes Flask Special?
Flask is a WSGI web application framework that follows a minimalist approach. Unlike Django, which comes with everything pre-configured, Flask gives you the essentials and lets you add what you need. This “micro” nature doesn’t mean Flask lacks power—it means you have the freedom to choose your components.
The framework is built on two main dependencies: Werkzeug (a WSGI utility library) and Jinja2 (a templating engine). Everything else is optional, which keeps your application lean and gives you complete architectural control.
Getting Started: Your First Flask Application
Let’s start with the classic Hello World example. First, install Flask:
pip install Flask
Now create a file called app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
Run it with python app.py and visit http://127.0.0.1:5000/ in your browser. That’s it—you have a working web application.
What’s happening here?
- We import Flask and create an application instance
- The
@app.route('/')decorator tells Flask which URL should trigger our function - The function returns the content we want to display
app.run(debug=True)starts the development server with debug mode enabled
Building Something Practical: A To-Do List Application
Let’s build a simple to-do list API to see Flask in action with more features. We’ll implement CRUD operations (Create, Read, Update, Delete) step by step.
Step 1: Project Setup
Create a new directory and set up your environment:
mkdir flask-todo
cd flask-todo
python -m venv venv
source venv/bin/activate # On Windows: source venv/Scripts/activate
pip install Flask
Step 2: Basic Application Structure
Create app.py:
from flask import Flask, jsonify, request
from datetime import datetime
app = Flask(__name__)
# In-memory storage (use a database in production)
todos = []
next_id = 1
@app.route('/')
def index():
return jsonify({"message": "Welcome to the To-Do API"})
if __name__ == '__main__':
app.run(debug=True)
Step 3: Create (POST) Endpoint
Add the ability to create new to-do items:
@app.route('/todos', methods=['POST'])
def create_todo():
global next_id
data = request.get_json()
if not data or 'title' not in data:
return jsonify({"error": "Title is required"}), 400
todo = {
"id": next_id,
"title": data['title'],
"description": data.get('description', ''),
"completed": False,
"created_at": datetime.now().isoformat()
}
todos.append(todo)
next_id += 1
return jsonify(todo), 201
Step 4: Read (GET) Endpoints
Add endpoints to retrieve to-do items:
@app.route('/todos', methods=['GET'])
def get_todos():
return jsonify(todos)
@app.route('/todos/<int:todo_id>', methods=['GET'])
def get_todo(todo_id):
todo = next((t for t in todos if t['id'] == todo_id), None)
if todo is None:
return jsonify({"error": "To-do not found"}), 404
return jsonify(todo)
Step 5: Update (PUT) Endpoint
Add the ability to update existing to-do items:
@app.route('/todos/<int:todo_id>', methods=['PUT'])
def update_todo(todo_id):
todo = next((t for t in todos if t['id'] == todo_id), None)
if todo is None:
return jsonify({"error": "To-do not found"}), 404
data = request.get_json()
todo['title'] = data.get('title', todo['title'])
todo['description'] = data.get('description', todo['description'])
todo['completed'] = data.get('completed', todo['completed'])
return jsonify(todo)
Step 6: Delete (DELETE) Endpoint
Add the ability to delete to-do items:
@app.route('/todos/<int:todo_id>', methods=['DELETE'])
def delete_todo(todo_id):
global todos
todo = next((t for t in todos if t['id'] == todo_id), None)
if todo is None:
return jsonify({"error": "To-do not found"}), 404
todos = [t for t in todos if t['id'] != todo_id]
return jsonify({"message": "To-do deleted successfully"})
Testing Your API
You can test the API using curl, Postman, or any HTTP client. Here are some curl examples:
# Create a to-do
curl -X POST http://127.0.0.1:5000/todos \
-H "Content-Type: application/json" \
-d '{"title": "Learn Flask", "description": "Build awesome web apps"}'
# Get all to-dos
curl http://127.0.0.1:5000/todos
# Get specific to-do
curl http://127.0.0.1:5000/todos/1
# Update a to-do
curl -X PUT http://127.0.0.1:5000/todos/1 \
-H "Content-Type: application/json" \
-d '{"completed": true}'
# Delete a to-do
curl -X DELETE http://127.0.0.1:5000/todos/1
Practical Tips for Flask Development
Use Blueprints for Larger Applications: As your application grows, organize your routes using Blueprints. This keeps your code modular and maintainable.
from flask import Blueprint
api = Blueprint('api', __name__, url_prefix='/api')
@api.route('/users')
def users():
return jsonify({"users": []})
# Register in your main app
app.register_blueprint(api)
Handle Errors Gracefully: Implement custom error handlers to provide consistent API responses.
@app.errorhandler(404)
def not_found(error):
return jsonify({"error": "Resource not found"}), 404
@app.errorhandler(500)
def internal_error(error):
return jsonify({"error": "Internal server error"}), 500
Use Environment Variables: Never hardcode sensitive information. Use environment variables and the python-dotenv package.
import os
from dotenv import load_dotenv
load_dotenv()
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['DATABASE_URL'] = os.getenv('DATABASE_URL')
Implement Request Validation: Validate incoming data to prevent errors and security issues. Consider using Flask-Marshmallow or Pydantic for complex validation.
Add Logging: Flask’s built-in logger helps track issues in production.
app.logger.info('Application started')
app.logger.error('An error occurred')
Use Flask Extensions Wisely: The Flask ecosystem has excellent extensions like Flask-SQLAlchemy (database), Flask-Migrate (database migrations), Flask-CORS (CORS handling), and Flask-JWT-Extended (authentication).
Structure Your Project Properly: For larger applications, use a proper structure:
flask-app/
├── app/
│ ├── __init__.py
│ ├── models.py
│ ├── routes.py
│ └── utils.py
├── tests/
├── config.py
├── requirements.txt
└── run.py
Enable Debug Mode in Development Only: Debug mode is great for development but dangerous in production as it exposes sensitive information.
Test Your Application: Write tests using pytest or unittest to ensure your application works correctly.
When to Choose Flask
Flask is ideal when you need flexibility and control. Choose Flask if you’re building a REST API, microservices, small to medium web applications, prototypes, or when you want to learn web development fundamentals without framework magic hiding the details.
For large applications with complex requirements where convention-over-configuration would save time, Django might be a better fit. But Flask’s flexibility makes it suitable even for large applications when properly structured.
Conclusion
Flask’s minimalist philosophy and flexibility make it a powerful tool for Python developers. Whether you’re building a simple API or a complex web application, Flask provides the foundation without imposing unnecessary constraints. The framework’s extensive ecosystem of extensions means you can add functionality as needed, keeping your application lean and focused.
Start small, like we did with the Hello World and To-Do list examples, and gradually add complexity as your requirements grow. Flask’s simplicity is its strength—embrace it, and you’ll build maintainable, efficient web applications.
Reference Links
- Flask Official Documentation – https://flask.palletsprojects.com – The most comprehensive and up-to-date resource for Flask, including tutorials, API references, and best practices.
- Miguel Grinberg’s Flask Mega-Tutorial – https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world – A detailed, multi-part tutorial that takes you from basics to advanced Flask concepts, written by one of the most respected voices in the Flask community.
- Real Python Flask Tutorials – https://realpython.com/tutorials/flask – High-quality tutorials covering various Flask topics, from beginner to advanced, with practical examples and clear explanations.
- Example – https://github.com/efernandes-tech/flask-001-ef-to-do-list


