Learn how to set up Django, create your first project, and build a simple web application from scratch. Perfect for beginners.
Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. In this tutorial, you'll build your first Django web application from scratch — a simple task manager — while learning the core concepts that make Django one of the most popular frameworks in the world.
Django was created in 2003 by web developers at the Lawrence Journal-World newspaper. It was released publicly in 2005 and has since become one of the most widely-used web frameworks. Companies like Instagram, Pinterest, Spotify, and Mozilla use Django in production.
Django follows the MVT (Model-View-Template) architectural pattern:
First, create a virtual environment and install Django:
# Create a project directory
mkdir my_first_django_app
cd my_first_django_app
# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install Django
pip install django
# Verify installation
python -m django --version
A Django project is the overall container for your web application. It holds configuration, settings, and one or more apps.
# Create the project
django-admin startproject taskmanager .
# The dot (.) tells Django to create files in the current directory
This creates the following structure:
my_first_django_app/
├── manage.py # Command-line utility
├── taskmanager/
│ ├── __init__.py # Python package marker
│ ├── settings.py # Project configuration
│ ├── urls.py # URL declarations
│ ├── asgi.py # ASGI entry point
│ └── wsgi.py # WSGI entry point
└── venv/ # Virtual environment
Let's test that everything works:
python manage.py runserver
Open http://127.0.0.1:8000/ in your browser. You should see the Django welcome page with a rocket ship. Congratulations — your first Django project is running!
In Django, an app is a module that handles a specific piece of functionality. A project can contain multiple apps.
python manage.py startapp tasks
Register the app in settings.py:
# taskmanager/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tasks', # Add your app here
]
Models define your database structure. Each model maps to a database table, and each field maps to a column.
# tasks/models.py
from django.db import models
from django.utils import timezone
class Task(models.Model):
PRIORITY_CHOICES = [
('low', 'Low'),
('medium', 'Medium'),
('high', 'High'),
]
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
completed = models.BooleanField(default=False)
priority = models.CharField(
max_length=10,
choices=PRIORITY_CHOICES,
default='medium'
)
created_at = models.DateTimeField(default=timezone.now)
due_date = models.DateField(null=True, blank=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.title
Now create and apply the migration:
# Create migration file
python manage.py makemigrations tasks
# Apply migration to database
python manage.py migrate
Django's built-in admin panel gives you a full CRUD interface for free:
# tasks/admin.py
from django.contrib import admin
from .models import Task
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('title', 'priority', 'completed', 'due_date', 'created_at')
list_filter = ('priority', 'completed')
search_fields = ('title', 'description')
list_editable = ('completed',)
Create a superuser account:
python manage.py createsuperuser
Visit http://127.0.0.1:8000/admin/ and log in. You can now add, edit, and delete tasks through the admin interface.
Views handle the logic of your application. Let's create views for listing, creating, and toggling tasks:
# tasks/views.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import Task
def task_list(request):
tasks = Task.objects.all()
return render(request, 'tasks/task_list.html', {'tasks': tasks})
def task_create(request):
if request.method == 'POST':
title = request.POST.get('title')
description = request.POST.get('description', '')
priority = request.POST.get('priority', 'medium')
if title:
Task.objects.create(
title=title,
description=description,
priority=priority
)
return redirect('task_list')
return render(request, 'tasks/task_create.html')
def task_toggle(request, pk):
task = get_object_or_404(Task, pk=pk)
task.completed = not task.completed
task.save()
return redirect('task_list')
def task_delete(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
task.delete()
return redirect('task_list')
URLs map web addresses to views:
# tasks/urls.py (create this file)
from django.urls import path
from . import views
urlpatterns = [
path('', views.task_list, name='task_list'),
path('create/', views.task_create, name='task_create'),
path('toggle/<int:pk>/', views.task_toggle, name='task_toggle'),
path('delete/<int:pk>/', views.task_delete, name='task_delete'),
]
# taskmanager/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('tasks.urls')),
]
Create the directory tasks/templates/tasks/ and add the list template:
<!-- tasks/templates/tasks/task_list.html -->
<h1>My Tasks</h1>
<a href="{% url 'task_create' %}">+ Add Task</a>
{% for task in tasks %}
<div class="task {% if task.completed %}completed{% endif %}">
<strong>{{ task.title }}</strong>
<small>({{ task.get_priority_display }})</small>
<form method="post" action="{% url 'task_toggle' task.pk %}">
{% csrf_token %}
<button>{% if task.completed %}Undo{% else %}Done{% endif %}</button>
</form>
</div>
{% empty %}
<p>No tasks yet!</p>
{% endfor %}
Notice the {% csrf_token %} tag in forms above. Django requires this token in every POST form to prevent Cross-Site Request Forgery attacks. If you forget it, you'll get a 403 error.
python manage.py runserver
Visit http://127.0.0.1:8000/ — you now have a working task manager with:
Django is a batteries-included web framework, meaning it provides out of the box nearly everything a web application needs — an ORM for the database, an admin interface, authentication, form handling, security protections, and a templating system. This is its great strength for getting started: rather than assembling a stack from many pieces, you get a coherent, well-integrated set of tools designed to work together, with sensible defaults and strong security built in. Understanding that Django aims to handle the common needs of web development for you, so you can focus on what makes your application unique, sets the right expectations for why it is such a productive starting point.
A Django project is organized into apps — self-contained modules each handling a piece of functionality — within an overall project that holds configuration. This structure encourages separating concerns: one app for accounts, another for a blog, another for a shop, each with its own models, views, and templates. Understanding this organization early helps you build maintainable applications, because it gives you a natural way to divide your code as it grows. Grasping the project-and-apps structure, and how Django's settings, URLs, and apps fit together, is the foundation that makes the rest of the framework comprehensible rather than mysterious.
At the core of how Django works is a simple flow: a request arrives at a URL, Django's URL configuration routes it to a view, the view does the work — often querying models and rendering a template — and returns a response. Understanding this path from URL to view to template to response is the mental model that makes everything else click, because every page in your application follows it. Once you see how a request flows through URLs, views, models, and templates to produce what the user sees, the pieces of Django stop being isolated concepts and become a coherent pipeline you can reason about and build within confidently.
Building your first app teaches the fundamentals, but Django has much more depth to grow into. After the basics, the natural next steps include the admin interface for managing data, forms for handling user input safely, authentication for user accounts, and the deployment process for getting your app online. Each builds on the foundation of models, views, URLs, and templates you started with. Knowing that these capabilities are there to learn next — and that they follow naturally from the fundamentals — turns a first app from an endpoint into a starting point, giving you a clear path from a working first project toward building real, complete applications.
You've built a functional Django application! Here are some next steps to continue learning:
| Topic | What You'll Learn |
|---|---|
| Django Forms | Use Django's form classes for validation and rendering |
| User Authentication | Add login, registration, and permissions |
| Static Files | Serve CSS, JavaScript, and images properly |
| Class-Based Views | Use Django's powerful generic views for less code |
| Django REST Framework | Build APIs for frontend frameworks or mobile apps |
| Deployment | Put your app online with Gunicorn and Nginx |
docs.djangoproject.com — it's one of the best docs in any framework. The official tutorial ("Writing your first Django app") goes even deeper into polls app concepts.