Skip to main content

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:

  1. Model: Defines your data structure and handles database interactions
  2. Template: Controls how the data is displayed (HTML, CSS, etc.)
  3. View: Contains the business logic and processes HTTP requests

Here's a visual representation of how these components interact:

  1. A user sends a request to the Django application
  2. The URL dispatcher directs the request to the appropriate view
  3. The view interacts with the model to retrieve or modify data
  4. The view renders a template with the model data
  5. 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:

bash
pip install django

Step 2: Create a New Django Project

Once Django is installed, you can create a new project:

bash
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:

bash
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:

bash
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:

python
# 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:

python
# 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:

bash
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:

python
# 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:

python
# 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:

python
# 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:

bash
mkdir -p blog/templates/blog

Then create a template file:

html
<!-- 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:

bash
python manage.py createsuperuser

Follow the prompts to set a username, email, and password.

Then, register your models in admin.py:

python
# 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

python
# 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

python
# 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

python
# 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:

html
<!-- 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:

html
<!-- 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

python
# 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:

bash
python manage.py makemigrations
python manage.py migrate

This will update your database with the new models.

Best Practices and Tips

  1. Organize your code: Keep your apps small and focused, following the single-responsibility principle.
  2. Use meaningful names: Choose clear and descriptive names for variables, functions, and classes.
  3. Write tests: Django has a built-in testing framework, use it to write tests for your views and models.
  4. Keep views slim: Business logic should be in models or helper functions, not views.
  5. Use Django's security features: Don't reinvent security mechanisms.
  6. Use Django's ORM properly: Avoid N+1 query problems using select_related() and prefetch_related().
  7. 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:

  1. Django Forms: For handling HTML forms and validation
  2. Class-based Views: A more object-oriented approach to views
  3. Django REST Framework: For building APIs
  4. Django Authentication: For user management and access control
  5. Testing in Django: How to write tests for your Django apps

Exercises

  1. Add Comments: Extend the blog app to allow visitors to leave comments on posts.
  2. User Profiles: Create user profile pages that show all posts by a particular author.
  3. Tags: Implement a tagging system for blog posts.
  4. Search: Add a search functionality to find posts by keywords.
  5. Deploy: Deploy your Django application to a hosting service like Heroku or PythonAnywhere.

Additional Resources

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! :)