Outsourced IT Partner
Support · systems · strategyOne person, one business — IT support here, websites at webology.online.
Django vs Flask: A Comprehensive Tutorial
Learn the fundamentals of two popular Python web frameworks
Python has become one of the most popular programming languages for web development, largely due to its simplicity, readability, and the powerful frameworks it offers. Two of the most widely used Python web frameworks are Django and Flask. In this tutorial, we'll explore both frameworks, understand their strengths and weaknesses, and learn how to build basic web applications with each.
Table of Contents
Introduction to Web Frameworks
Web frameworks provide a structured way to build and deploy web applications. They handle many of the common tasks and challenges in web development, allowing developers to focus on building the unique features of their applications rather than reinventing the wheel.
Python web frameworks typically provide tools and libraries for:
- URL routing (mapping URLs to code)
- HTML templating (generating HTML dynamically)
- Database access and ORM (Object-Relational Mapping)
- Session management and user authentication
- Security features (protection against common vulnerabilities)
- Form handling and validation
Django and Flask represent two different philosophies in the world of web frameworks:
Django
A "batteries-included" framework that provides almost everything you need out of the box.
- Full-featured and opinionated
- Built-in admin interface
- Integrated ORM
- Authentication system
- Form handling
Flask
A microframework that provides the essentials while keeping the core simple and extensible.
- Lightweight and flexible
- Minimal core functionality
- Extensible through add-ons
- Less opinionated
- More control over components
Django: The Batteries-Included Framework
Overview & Features
Django was created in 2003 and released publicly in 2005. It was designed with news websites in mind, which typically need to be built quickly, securely, and with the ability to handle high traffic.
Django follows the "batteries-included" philosophy, providing a comprehensive set of tools and features out of the box:
- ORM (Object-Relational Mapper): Interact with your database using Python objects instead of SQL
- Admin Interface: A ready-to-use interface for managing your site's content
- Authentication System: User accounts, groups, permissions, and cookie-based sessions
- Caching Framework: Hook into memcached or other caching systems
- Form Handling: Define forms, validate input, and process submissions
- Testing Framework: Tools for writing and running tests
- Internationalization: Support for multiple languages and time zones
Installation & Setup
Let's start by installing Django. It's recommended to use a virtual environment to keep your project dependencies isolated.
# Create a virtual environment
python -m venv django_env
# Activate the virtual environment
# On Windows:
django_env\Scripts\activate
# On macOS/Linux:
source django_env/bin/activate
# Install Django
pip install django
# Verify installation
python -m django --version
Creating Your First Django Project
Once Django is installed, you can create a new project:
# Create a new Django project
django-admin startproject mysite
# Navigate to the project directory
cd mysite
# Run the development server
python manage.py runserver
Now you can visit http://127.0.0.1:8000/ in your browser to see your new Django project in action!
Let's understand the project structure:
mysite/
manage.py # Command-line utility for administrative tasks
mysite/ # Project package
__init__.py # Empty file that tells Python this is a package
settings.py # Project settings/configuration
urls.py # URL declarations for the project
asgi.py # Entry point for ASGI-compatible web servers
wsgi.py # Entry point for WSGI-compatible web servers
Now, let's create an app within our project. In Django, a project can contain multiple apps, and each app serves a specific purpose:
# Create a new app
python manage.py startapp polls
This creates a new directory with the following structure:
polls/
__init__.py # Empty file that tells Python this is a package
admin.py # Register models with the admin interface
apps.py # App configuration
migrations/ # Database migrations
__init__.py
models.py # Data models
tests.py # Test cases
views.py # View functions
Working with Models & Databases
Django's ORM allows you to define your data models as Python classes. Let's create a simple model for a poll application:
# polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
After defining your models, you need to:
- Add your app to
INSTALLED_APPSinsettings.py - Create migrations
- Apply migrations to create the database tables
# Add 'polls' to INSTALLED_APPS in mysite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls', # Add this line
]
# Create migrations
python manage.py makemigrations polls
# Apply migrations
python manage.py migrate
Views & Templates
Views in Django handle the logic for processing requests and returning responses. Let's create a simple view to display a list of questions:
# polls/views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
Now, we need to create a template to render the data:
# Create directory: polls/templates/polls/
# Create file: polls/templates/polls/index.html
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Finally, we need to map a URL to our view:
# Create file: polls/urls.py
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
]
# Update mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
The Admin Interface
One of Django's most powerful features is its automatic admin interface. To use it, you need to:
- Create a superuser
- Register your models with the admin site
# Create a superuser
python manage.py createsuperuser
# Register models in polls/admin.py
from django.contrib import admin
from .models import Question, Choice
admin.site.register(Question)
admin.site.register(Choice)
Now you can visit http://127.0.0.1:8000/admin/ and log in with your superuser credentials to manage your site's content.
Flask: The Microframework
Overview & Features
Flask was created in 2010 as a lightweight alternative to more comprehensive frameworks. It's designed to be simple, flexible, and easy to extend.
Flask follows the "microframework" philosophy, providing a minimal core with the ability to add extensions as needed:
- Routing: Map URLs to Python functions
- Templating: Jinja2 templating engine
- Development Server: Built-in server for development
- Debugger: Interactive debugger for development
- RESTful Request Handling: Access request data easily
- Unit Testing Support: Built on Werkzeug and unittest
Everything else (database access, form validation, authentication, etc.) is provided through extensions or can be implemented by the developer.
Installation & Setup
Let's start by installing Flask. As with Django, it's recommended to use a virtual environment:
# Create a virtual environment
python -m venv flask_env
# Activate the virtual environment
# On Windows:
flask_env\Scripts\activate
# On macOS/Linux:
source flask_env/bin/activate
# Install Flask
pip install flask
# Verify installation
python -c "import flask; print(flask.__version__)"
Creating Your First Flask Application
Creating a Flask application is remarkably simple. Here's a minimal example:
# 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 this script with python app.py, and you'll have a web server running at http://127.0.0.1:5000/.
For larger applications, you might want to use a more structured approach. Here's a common project structure for Flask applications:
myflaskapp/
app/
__init__.py # Initialize the Flask application
views/ # View functions
models/ # Data models
templates/ # Jinja2 templates
static/ # Static files (CSS, JS, images)
config.py # Configuration settings
requirements.txt # Dependencies
run.py # Script to run the application
Routing & Views
Flask uses decorators to define routes. Here's how you can define multiple routes:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World!'
@app.route('/user/<username>')
def show_user_profile(username):
return f'User {username}'
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'Post {post_id}'
Flask supports variable rules in URLs, as shown in the /user/<username> and /post/<int:post_id> examples. You can also specify the HTTP methods that a route should respond to:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
# Process the login form
return 'Processing login'
else:
# Show the login form
return 'Please log in'
Templates & Static Files
Flask uses Jinja2 for templating. Templates are stored in the templates directory, and static files (CSS, JavaScript, images) are stored in the static directory.
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
<!-- templates/hello.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello from Flask</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
Jinja2 templates support variables, filters, control structures, and template inheritance, making it easy to create complex layouts with reusable components.
Working with Extensions
Flask's power comes from its extensibility. There are extensions for almost everything you might need:
- Flask-SQLAlchemy: ORM for database access
- Flask-WTF: Form handling and validation
- Flask-Login: User authentication
- Flask-RESTful: Building REST APIs
- Flask-Migrate: Database migrations
- Flask-Admin: Admin interface
Let's see how to use Flask-SQLAlchemy for database access:
# Install Flask-SQLAlchemy
pip install flask-sqlalchemy
# app.py
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db'
db = SQLAlchemy(app)
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(200), nullable=False)
def __repr__(self):
return f'<Todo {self.id}>'
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
todo_content = request.form['content']
new_todo = Todo(content=todo_content)
try:
db.session.add(new_todo)
db.session.commit()
return redirect('/')
except:
return 'There was an issue adding your todo'
else:
todos = Todo.query.all()
return render_template('index.html', todos=todos)
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
Django vs Flask: A Detailed Comparison
Now that we've explored both frameworks, let's compare them across various dimensions:
| Feature | Django | Flask |
|---|---|---|
| Philosophy | Batteries-included, opinionated | Microframework, flexible |
| Learning Curve | Steeper (more concepts to learn) | Gentler (simpler core) |
| Project Structure | Enforced, consistent | Flexible, up to the developer |
| Database | Built-in ORM | Extensions (e.g., SQLAlchemy) |
| Admin Interface | Built-in, powerful | Extensions (e.g., Flask-Admin) |
| Authentication | Built-in | Extensions (e.g., Flask-Login) |
| Forms | Built-in | Extensions (e.g., Flask-WTF) |
| Templating | Django Templates | Jinja2 (similar but more powerful) |
| Routing | URL patterns in urls.py | Decorators on view functions |
| Development Speed | Faster for standard features | Faster for custom, unique features |
| Flexibility | Less flexible (follows Django's way) | More flexible (build it your way) |
| Community & Ecosystem | Larger, more established | Growing rapidly |
When to Use Each Framework
When to Use Django
- Building content-heavy sites (blogs, news sites)
- Projects with standard features (user accounts, admin panels)
- When you need to move quickly with a full-featured site
- Large, complex applications with many components
- Teams that benefit from enforced structure
- Projects where security is a top priority
When to Use Flask
- Building small to medium-sized applications
- Projects with unique, non-standard requirements
- When you need fine-grained control over components
- API services and microservices
- Prototyping and experimentation
- Learning web development concepts
Conclusion & Next Steps
Both Django and Flask are excellent frameworks with their own strengths and ideal use cases. Django provides a comprehensive, integrated solution that's perfect for building full-featured websites quickly. Flask offers a lightweight, flexible foundation that's ideal for custom applications and APIs.
The best way to decide which framework is right for you is to try both and see which aligns better with your thinking and project needs.
Next Steps for Learning Django:
- Complete the official Django Tutorial
- Explore Django's documentation for deeper understanding
- Build a simple CRUD application
- Learn about Django REST framework for building APIs
- Explore Django's deployment options
Next Steps for Learning Flask:
- Complete the official Flask Tutorial
- Explore popular Flask extensions
- Build a RESTful API
- Learn about application factories and blueprints for larger applications
- Explore Flask's deployment options
Remember, the goal is not to find the "best" framework, but the one that's best for your specific needs and preferences. Happy coding!