Django Essentials: Step-by-Step Learning

Tomás Manzur
Django Unleashed
Published in
11 min readJun 17, 2024
Django_tutorial

→ Django Tutorial in HTML Version

What is Django?

Django is a powerful and flexible Python-based web framework designed to streamline the development process of web applications. It focuses on making web development faster and more straightforward by offering reusable components, encouraging rapid development, and adhering to the “Don’t Repeat Yourself” (DRY) principle. Django comes with numerous built-in features, including an ORM (Object-Relational Mapping) for database interactions, a comprehensive authentication system, and a user-friendly admin interface for managing application data.

Key Features of Django

  • Rapid Development: Django includes many built-in functionalities that reduce the time and effort needed to build complex web applications.
  • Scalability: Designed to accommodate the needs of both small and large-scale projects.
  • Security: Django helps developers avoid many common security mistakes, including SQL injection, cross-site scripting, and cross-site request forgery.
  • Versatility: Suitable for a variety of projects, from simple websites to complex web applications.

What Can You Build with Django?

Django’s versatility allows it to be used for building a wide range of web applications. Here are some examples:

Types of Applications

  • Content Management Systems (CMS): Manage and organize web content easily.
  • E-commerce Websites: Handle product listings, shopping carts, and payment gateways.
  • Social Media Platforms: Create user profiles, messaging systems, and activity feeds.
  • Scientific Computing Platforms: Manage and analyze large datasets and complex computations.
  • APIs: Using Django REST Framework to create robust and scalable APIs.
  • Web Applications with Complex Data Requirements: Handle intricate business logic and large volumes of data efficiently.

Difference Between a Project and an App in Django

Understanding the distinction between a project and an app is crucial for organizing your Django codebase effectively.

Project

A Django project is a collection of settings and configurations for your web application. It defines the overall structure and behavior of your site. A project typically includes:

  • Global Settings: Configurations that apply to the entire project, such as database settings and middleware.
  • URL Routing: A central place to define the URL patterns for the project.
  • Project-Specific Files: Such as settings.py, urls.py, and wsgi.py.

App

An app is a self-contained module within a Django project that handles specific functionalities. Each app is responsible for a distinct part of your application. For example, an e-commerce project might have separate apps for managing products, orders, and users. An app includes:

  • Models: Define the data structure and interact with the database.
  • Views: Handle the logic for displaying data and processing user input.
  • Templates: Define the HTML structure for rendering data.
  • Static Files: Contain assets like CSS, JavaScript, and images.

How to Start a Django Project

To create a new Django project, you can use the django-admin command-line utility. This utility sets up the initial project structure, including essential configuration files.

Command to Create a Project

django-admin startproject projectname

Generated Project Structure

projectname/
manage.py
projectname/
__init__.py
settings.py
urls.py
wsgi.py
  • manage.py: A command-line utility to manage your project, including running the development server and performing database migrations.
  • projectname/settings.py: The configuration file for your project, containing settings for databases, installed apps, middleware, and more.
  • projectname/urls.py: The URL configuration file, mapping URL patterns to views.
  • projectname/wsgi.py: An entry-point for WSGI-compatible web servers to serve your project.

How to Start a Django App

Within a Django project, you can create multiple apps to modularize your functionality. Each app is a Python package with a specific directory structure.

Command to Create an App

python manage.py startapp appname

Generated App Structure

appname/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
  • models.py: Defines the data models (database schema) for the app.
  • views.py: Contains the logic for handling requests and returning responses.
  • admin.py: Configures the admin interface for managing app data.
  • migrations/: Directory to store database migration files.

How to Run the Development Server

Django comes with a lightweight development server that allows you to test your application locally. This server is not suitable for production but is perfect for development and testing.

Command to Start the Server

python manage.py runserver

Accessing the Development Server

Once the server is running, you can access your application at http://127.0.0.1:8000/. This URL points to your local machine's IP address and port 8000.

Understanding the settings.py File

The settings.py file is the heart of your Django project configuration. It contains various settings that control the behavior of your application.

Key Configurations in settings.py

  • DEBUG: A boolean that should be set to True during development for detailed error messages and False in production.
  • ALLOWED_HOSTS: A list of strings representing the host/domain names that the Django site can serve.
  • DATABASES: Configuration for connecting to your database. Example:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / "db.sqlite3",
}
}
  • INSTALLED_APPS: A list of applications that are enabled in your project. Each app is represented by a string of its full Python path.
  • MIDDLEWARE: A list of middleware components that process requests and responses.
  • TEMPLATES: Configuration for the template engine, including the directories to search for templates and context processors.

Example Configuration Snippet

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}

Models, Views, and Templates (MVT) in Django

The MVT pattern in Django separates concerns into three main components: Models, Views, and Templates.

Models

Models define the structure of your database. Each model class represents a table in the database, and each attribute of the class represents a field in the table.

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()

Views

Views handle the logic of your application. They process user requests, interact with models to fetch data, and return responses.

from django.shortcuts import render
from .models import Author

def author_list(request):
authors = Author.objects.all()
return render(request, 'author_list.html', {'authors': authors})

Templates

Templates define the presentation layer of your application. They are HTML files that display data provided by the views.

<!DOCTYPE html>
<html>
<head>
<title>Author List</title>
</head>
<body>
<h1>Author List</h1>
<ul>
{% for author in authors %}
<li>{{ author.name }} ({{ author.age }} years old)</li>
{% endfor %}
</ul>
</body>
</html>

URL Patterns and Configuration

URL patterns define the routes for your application, mapping URLs to views. This is configured using the urlpatterns list.

Example Configuration

from django.urls import path
from . import views

urlpatterns = [
path('', views.home, name='home'),
path('authors/', views.author_list, name='author_list'),
]

Including App URLs in Project URL Configuration

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
path('admin/', admin.site.urls),
path('', include('appname.urls')),
]

Django Admin Panel

The Django admin interface is a powerful tool that allows you to manage your application data easily. It provides a web-based interface to create, update, delete, and view the data models.

Enabling the Admin Interface

  1. Add your app to INSTALLED_APPS in settings.py:
INSTALLED_APPS = [     ...     'appname', ]

2. Register models in admin.py:

from django.contrib import admin
from .models import Author

admin.site.register(Author)

3. Create a superuser to access the admin interface:

python manage.py createsuperuser

4. Run the development server and visit http://127.0.0.1:8000/admin to log in.

makemigrations and migrate in Django

makemigrations

This command generates migration files based on the changes you make to your models. Migrations are a way of propagating changes you make to your models into the database schema.

python manage.py makemigrations

migrate

This command applies the migrations to your database, updating the schema to match your models.

python manage.py migrate

Class-Based vs. Function-Based Views

Function-Based Views (FBV)

Function-based views are simple and easy to use, especially for straightforward logic.

from django.http import HttpResponse

def home(request):
return HttpResponse("Welcome to the home page!")

Class-Based Views (CBV)

Class-based views provide a more organized and reusable structure, making them ideal for more complex applications.

from django.views import View
from django.http import HttpResponse

class HomeView(View):
def get(self, request):
return HttpResponse("Welcome to the home page!")

Preference

Class-based views are preferred for their scalability and organization, especially in larger applications where reusability and modularity are crucial.

Preferred Databases with Django

Django supports multiple databases, each with its advantages and use cases.

Commonly Used Databases

  • SQLite: Suitable for development and testing due to its simplicity and zero configuration.
  • PostgreSQL: Preferred for production environments because of its robustness, advanced features, and reliability.
  • MySQL: Another popular choice for production, known for its speed and wide usage.

Configuring Database Connection in Django

In settings.py, you can configure the database connection settings for your Django project.

Example Configuration for PostgreSQL

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}

Dynamic URL Access in Django

Django provides utilities to dynamically generate URLs, making your application more maintainable and robust.

Using reverse in Views

from django.urls import reverse
from django.shortcuts import redirect

def my_view(request):
url = reverse('my_view_name')
return redirect(url)

Using {% url %} in Templates

<a href="{% url 'my_view_name' %}">Go to my view</a>

Storing Templates in Django

Templates are usually stored in the templates directory within each app or in a global templates directory.

Example Structure

appname/
templates/
appname/
my_template.html

Configuring settings.py to Include Template Directories

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Understanding Double Curly Braces {{ }} in Templates

In Django templates, double curly braces {{ }} are used to render variables passed from views.

Example

<p>Hello, {{ user.username }}!</p>

This will display the username of the logged-in user.

Using {% %} in Django Templates

The {% %} syntax is used for template tags, which provide logic and control structures within templates.

Example of a Loop

<ul>
{% for author in authors %}
<li>{{ author.name }}</li>
{% endfor %}
</ul>

This loop will iterate over the authors queryset and render each author's name in an unordered list.

Including and Extending Templates

Including Templates

Including templates allows you to reuse common sections like headers or footers across multiple templates.

{% include 'header.html' %}

Extending Templates

Template inheritance allows you to create a base template and extend it in other templates, promoting DRY principles.

{% extends 'base.html' %}
{% block content %}
<h1>Welcome</h1>
{% endblock %}

This extends base.html and defines content for the content block.

Static Files in Django

What are Static Files?

Static files are files like CSS, JavaScript, and images that are not dynamically generated by the server but are necessary for your application.

Including Static Files

To include static files in your Django project:

  1. Create a static directory in your app folder.
  2. Configure settings.py:
STATIC_URL = '/static/' STATICFILES_DIRS = [     BASE_DIR / "static", ]

3. Load static files in templates:

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<script src="{% static 'js/script.js' %}"></script>

Configuring Static Files in Development

During development, Django can serve static files for you. Ensure django.contrib.staticfiles is included in INSTALLED_APPS, then use python manage.py runserver to serve static files automatically.

What is Media Root?

MEDIA_ROOT is a setting in Django that defines the directory where user-uploaded files are stored.

Configuring Media Root

  1. Add the media root and URL settings to settings.py:
MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media'

2. Serve media files during development:

from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

This configuration ensures that media files are accessible during development.

What is collectstatic in Django?

collectstatic is a Django management command that collects all static files from your apps and places them in a single directory specified by the STATIC_ROOT setting.

Using collectstatic

  1. Configure settings.py:
STATIC_ROOT = BASE_DIR / 'staticfiles'

2. Run the command:

python manage.py collectstatic
  • python manage.py collectstatic

Serving Static Files in Production

In production, you’ll need a web server like Nginx to serve static files. Configure your web server to serve files from the STATIC_ROOT directory.

Foreign Keys in Django

A Foreign Key is a field that creates a many-to-one relationship between models. It is used to link one model to another.

Defining a Foreign Key

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)

In this example, each Book is linked to an Author.

Querying with Foreign Keys

books_by_author = Book.objects.filter(author__name='Author Name')

This query retrieves all books written by a specific author.

One-to-One Field in Django

A One-to-One Field creates a one-to-one relationship between models. This is similar to a foreign key with a unique constraint.

Defining a One-to-One Field

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()

Each Profile is associated with a single User.

Many-to-Many Field in Django

A Many-to-Many Field creates a many-to-many relationship between models, allowing each instance of one model to be associated with multiple instances of another model.

Defining a Many-to-Many Field

class Student(models.Model):
name = models.CharField(max_length=100)

class Course(models.Model):
title = models.CharField(max_length=200)
students = models.ManyToManyField(Student)

Each Course can have multiple Students, and each Student can enroll in multiple Courses.

Character Field Attributes in Django

Common Attributes for Character Fields

  • max_length: Defines the maximum length of the field.
  • default: Sets a default value for the field.
  • null: Allows NULL values in the database.
  • blank: Allows the field to be blank in forms.

Example

class Author(models.Model):
name = models.CharField(max_length=100, default='Anonymous')

This example creates a name field with a maximum length of 100 characters and a default value of 'Anonymous'.

Basic Database Queries in Django

Creating Objects

author = Author.objects.create(name='John Doe')

This command creates a new Author object and saves it to the database.

Retrieving All Objects

authors = Author.objects.all()

This query retrieves all Author objects from the database.

Retrieving a Single Object

author = Author.objects.get(id=1)

This query retrieves the Author object with the specified ID.

Filtering Objects

young_authors = Author.objects.filter(age__lt=30)

This query retrieves all authors who are younger than 30 years old.

Querying a Single Element from a Database Table

Example

author = Author.objects.get(id=1)

Handling DoesNotExist Exception

from django.core.exceptions import ObjectDoesNotExist

try:
author = Author.objects.get(id=1)
except ObjectDoesNotExist:
print("Author not found")

This ensures your application handles cases where the queried object does not exist.

Filtering Items by Multiple Attributes

Example

authors = Author.objects.filter(age__lt=30, name__icontains='john')

This query retrieves authors who are younger than 30 years old and whose name contains ‘john’.

Model Sets and Their Usage

A QuerySet is a collection of database queries. It allows you to read data from the database, filter it, and order it.

Example

authors = Author.objects.filter(age__lt=30).order_by('name')

This QuerySet retrieves authors younger than 30 and orders them by name.

Querying Upwards in a Model Relationship

Example

books = Book.objects.filter(author__name='John Doe')

This query retrieves all books written by the author named ‘John Doe’.

CSRF Tokens and Their Usage

CSRF (Cross-Site Request Forgery) tokens are used to protect forms from CSRF attacks, ensuring that the form submission is coming from the authenticated user.

Using CSRF Tokens

<form method="post">
{% csrf_token %}
<!-- form fields -->
</form>

This adds a hidden field with a CSRF token to the form.

Model Forms in Django

Model forms allow you to create forms directly from your models, ensuring that the form fields match the model fields.

Creating a Model Form

from django import forms
from .models import Author

class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ['name', 'age']

This form can be used to create or update Author instances.

Django REST Framework (DRF) and Its Importance

Django REST Framework (DRF) is a powerful and flexible toolkit for building Web APIs in Django. It simplifies the process of building RESTful APIs, offering a wide range of features out of the box.

Why Use DRF?

  • Flexibility: Provides a customizable and modular approach to building APIs.
  • Serialization: Converts complex data types, such as querysets and model instances, into native Python data types.
  • Authentication: Supports various authentication methods, including token-based authentication and OAuth.
  • Pagination: Easily add pagination to API responses.
  • Browsable API: Automatically generates a web-based interface for your API.

Signals in Django

Signals allow you to execute some code when certain events occur. They provide a way to decouple different parts of your application.

Example: Post-Save Signal

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Author

@receiver(post_save, sender=Author)
def author_saved(sender, instance, **kwargs):
print(f'Author {instance.name} saved.')

This signal is triggered every time an Author instance is saved, printing a message to the console.

Preventing Unauthorized Users from Viewing Certain Pages

Using the login_required Decorator

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
return HttpResponse("Hello, authenticated user!")

This decorator restricts access to the view, ensuring that only authenticated users can access it.

Serializers in Django REST Framework

Serializers convert complex data types, such as querysets and model instances, into native Python data types that can be rendered into JSON, XML, or other content types.

Example

from rest_framework import serializers
from .models import Author

class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'age']

This serializer converts Author instances to a JSON representation and vice versa.

--

--

Tomás Manzur
Django Unleashed

Data scientist and Python developer with a PhD in sociology. Passionate about leveraging data to drive insights and solutions.