Python Django Basics
Introduction
Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. It was created in the early 2000s and has since become one of the most popular web frameworks for Python. Django follows the "batteries-included" philosophy, meaning it comes with many built-in features that help developers build web applications quickly without having to reinvent the wheel.
In this guide, we'll explore the fundamentals of Django, understand its architecture, and build a simple web application step by step.
What is Django?
Django is a full-stack web framework that takes care of much of the hassle of web development, allowing you to focus on writing your app without needing to reinvent the wheel. It's free, open-source, and used by organizations such as Instagram, Mozilla, and NASA.
Key features of Django include:
- Rapid development: Django's "batteries-included" approach means less code and faster development
- Security: Protection against common security threats like SQL injection, cross-site scripting, etc.
- Scalability: Django can scale to handle high traffic demands
- Versatility: Used for everything from content management systems to social networks
- ORM (Object-Relational Mapper): Interact with your database using Python instead of SQL
- Admin interface: Auto-generated admin panels for managing content
Django's Architecture: MTV
Django follows an MTV (Model-Template-View) architecture, which is similar to the MVC (Model-View-Controller) pattern but with Django-specific terminology:
- Model: Defines your data structure and handles database interactions
- Template: Controls how the data is displayed (HTML, CSS, etc.)
- View: Contains the business logic and processes HTTP requests
Here's a visual representation of how these components interact:
- A user sends a request to the Django application
- The URL dispatcher directs the request to the appropriate view
- The view interacts with the model to retrieve or modify data
- The view renders a template with the model data
- The rendered HTML is sent back to the user's browser
Setting Up Your First Django Project
Prerequisites
Before we begin, make sure you have:
- Python 3.6 or higher installed
- pip (Python package manager)
- A basic understanding of Python
Step 1: Install Django
Let's start by installing Django using pip:
pip install django
Step 2: Create a New Django Project
Once Django is installed, you can create a new project:
django-admin startproject mysite
This creates a directory called mysite
with the following structure:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
- manage.py: A command-line utility that helps you interact with your project
- mysite/: The actual Python package for your project
- settings.py: Project configuration
- urls.py: URL declarations for your project
- asgi.py and wsgi.py: Entry points for ASGI and WSGI compatible web servers
Step 3: Run the Development Server
Navigate to your project directory and start the development server:
cd mysite
python manage.py runserver
You should see output like:
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
March 23, 2023 - 15:50:53
Django version 4.1.7, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Open your browser and go to http://127.0.0.1:8000/
. You should see Django's welcome page with a "Congratulations!" message.
Step 4: Create an App
In Django, a project is a collection of apps. Let's create our first app:
python manage.py startapp blog
This creates a new directory called blog
with several files:
blog/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
Step 5: Register Your App
To include our app in the project, we need to add it to the INSTALLED_APPS
list in settings.py
:
# mysite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # Add your app here
]
Models: Defining Your Data
Models define the structure of your database and are declared in models.py
. Let's create a simple blog post model:
# blog/models.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
After creating or modifying models, we need to create migrations and apply them:
python manage.py makemigrations blog
python manage.py migrate
The makemigrations
command creates migration files based on your model changes, and migrate
applies those changes to the database.
Views: Processing Requests
Views handle the logic of your application and are defined in views.py
. Let's create a simple view:
# blog/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
def home(request):
return HttpResponse("Welcome to my blog!")
def post_list(request):
posts = Post.objects.all().order_by('-pub_date')
return render(request, 'blog/post_list.html', {'posts': posts})
URLs: Mapping URLs to Views
We need to map URLs to our views. First, create a urls.py
file in the blog app:
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('posts/', views.post_list, name='post_list'),
]
Then, include these URLs in the project's main urls.py
:
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
]
Templates: Rendering HTML
Templates define how data is presented to users. Let's create a template for our blog posts.
First, create a directory structure for templates:
mkdir -p blog/templates/blog
Then create a template file:
<!-- blog/templates/blog/post_list.html -->
<!DOCTYPE html>
<html>
<head>
<title>My Blog</title>
</head>
<body>
<h1>Blog Posts</h1>
{% if posts %}
<ul>
{% for post in posts %}
<li>
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
<small>Published: {{ post.pub_date }}</small>
</li>
{% endfor %}
</ul>
{% else %}
<p>No posts available.</p>
{% endif %}
</body>
</html>
Admin Interface
Django comes with a powerful admin interface out of the box. To use it, first create a superuser:
python manage.py createsuperuser
Follow the prompts to set a username, email, and password.
Then, register your models in admin.py
:
# blog/admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
Now you can access the admin interface at http://127.0.0.1:8000/admin/
and manage your blog posts.
Building a Complete Blog Application
Let's put everything together to create a more complete blog application.
Enhanced Models
# blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Categories"
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return self.title
Enhanced Views
# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post, Category
def home(request):
latest_posts = Post.objects.order_by('-pub_date')[:5]
categories = Category.objects.all()
context = {
'latest_posts': latest_posts,
'categories': categories,
}
return render(request, 'blog/home.html', context)
def post_detail(request, post_id):
post = get_object_or_404(Post, pk=post_id)
return render(request, 'blog/post_detail.html', {'post': post})
def category_posts(request, category_id):
category = get_object_or_404(Category, pk=category_id)
posts = Post.objects.filter(category=category).order_by('-pub_date')
return render(request, 'blog/category_posts.html',
{'category': category, 'posts': posts})
Enhanced URLs
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('post/<int:post_id>/', views.post_detail, name='post_detail'),
path('category/<int:category_id>/', views.category_posts, name='category_posts'),
]
Enhanced Templates
For the home page:
<!-- blog/templates/blog/home.html -->
<!DOCTYPE html>
<html>
<head>
<title>My Django Blog</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 20px; }
.container { max-width: 1000px; margin: 0 auto; }
.header { border-bottom: 1px solid #ccc; margin-bottom: 20px; padding-bottom: 10px; }
.sidebar { float: right; width: 30%; }
.main { width: 65%; }
.post { margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px dotted #ccc; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>My Django Blog</h1>
</div>
<div class="sidebar">
<h2>Categories</h2>
<ul>
{% for category in categories %}
<li><a href="{% url 'category_posts' category.id %}">{{ category.name }}</a></li>
{% empty %}
<li>No categories yet.</li>
{% endfor %}
</ul>
</div>
<div class="main">
<h2>Latest Posts</h2>
{% for post in latest_posts %}
<div class="post">
<h3><a href="{% url 'post_detail' post.id %}">{{ post.title }}</a></h3>
<p>{{ post.content|truncatewords:30 }}</p>
<small>By {{ post.author }} on {{ post.pub_date }}</small>
</div>
{% empty %}
<p>No posts yet.</p>
{% endfor %}
</div>
</div>
</body>
</html>
For post details:
<!-- blog/templates/blog/post_detail.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }} - My Django Blog</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 20px; }
.container { max-width: 800px; margin: 0 auto; }
.back-link { margin-bottom: 20px; }
.post-meta { color: #666; margin-bottom: 20px; }
</style>
</head>
<body>
<div class="container">
<div class="back-link">
<a href="{% url 'home' %}">← Back to Home</a>
</div>
<article>
<h1>{{ post.title }}</h1>
<div class="post-meta">
By {{ post.author }} on {{ post.pub_date }}
{% if post.category %}
in <a href="{% url 'category_posts' post.category.id %}">{{ post.category.name }}</a>
{% endif %}
</div>
<div class="post-content">
{{ post.content|linebreaks }}
</div>
</article>
</div>
</body>
</html>
Register in Admin
# blog/admin.py
from django.contrib import admin
from .models import Category, Post
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'pub_date', 'category')
list_filter = ('pub_date', 'category', 'author')
search_fields = ('title', 'content')
date_hierarchy = 'pub_date'
admin.site.register(Category)
admin.site.register(Post, PostAdmin)
After making these changes, run:
python manage.py makemigrations
python manage.py migrate
This will update your database with the new models.
Best Practices and Tips
- Organize your code: Keep your apps small and focused, following the single-responsibility principle.
- Use meaningful names: Choose clear and descriptive names for variables, functions, and classes.
- Write tests: Django has a built-in testing framework, use it to write tests for your views and models.
- Keep views slim: Business logic should be in models or helper functions, not views.
- Use Django's security features: Don't reinvent security mechanisms.
- Use Django's ORM properly: Avoid N+1 query problems using
select_related()
andprefetch_related()
. - Use template inheritance: Create a base template and extend it for specific pages.
Summary
In this guide, we've covered the basics of Django:
- Setting up a Django project and creating apps
- Understanding the MTV (Model-Template-View) architecture
- Creating models to define your data structure
- Creating views to handle business logic
- Using templates to render HTML
- Setting up URL patterns to map URLs to views
- Using the Django admin interface
- Building a complete blog application
Django's comprehensive approach makes it an excellent choice for both beginners and experienced developers. Its "batteries-included" philosophy means you can get started quickly without having to integrate multiple libraries or frameworks.
Further Learning
To continue your Django journey, consider exploring:
- Django Forms: For handling HTML forms and validation
- Class-based Views: A more object-oriented approach to views
- Django REST Framework: For building APIs
- Django Authentication: For user management and access control
- Testing in Django: How to write tests for your Django apps
Exercises
- Add Comments: Extend the blog app to allow visitors to leave comments on posts.
- User Profiles: Create user profile pages that show all posts by a particular author.
- Tags: Implement a tagging system for blog posts.
- Search: Add a search functionality to find posts by keywords.
- Deploy: Deploy your Django application to a hosting service like Heroku or PythonAnywhere.
Additional Resources
- Django Official Documentation
- Django Girls Tutorial
- Django for Beginners by William S. Vincent
- Two Scoops of Django - A best practices book
- MDN Django Web Framework
Happy coding with Django!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)