1. Skip to content

1. Django Cheat Sheet

This cheat sheet provides an exhaustive overview of the Django web framework, covering essential commands, concepts, and code snippets for efficient Django development. It aims to be a one-stop reference for common tasks and best practices.

1.1 Getting Started

1.1.1 Installation

pip install django

Consider using a virtual environment:

python -m venv venv
source venv/bin/activate  # On Linux/macOS
venv\Scripts\activate  # On Windows

1.1.2 Create a Project

django-admin startproject myproject
cd myproject

1.1.3 Create an App

python manage.py startapp myapp

1.1.4 Run the Development Server

python manage.py runserver

1.2 Models

1.2.1 Define a Model (models.py)

from django.db import models

class MyModel(models.Model):
    name = models.CharField(max_length=100, help_text="Enter the name")
    description = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True)
    order = models.PositiveIntegerField(default=0)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['order', '-created_at']  # Default ordering
        verbose_name = "My Model Entry"
        verbose_name_plural = "My Model Entries"

1.2.2 Model Fields

  • AutoField: An auto-incrementing integer field (primary key by default).
  • BigAutoField: A 64-bit integer, similar to AutoField.
  • CharField: For short to medium-length strings. max_length is required.
  • TextField: For long strings of unlimited length. blank=True allows the field to be empty in forms, null=True allows the field to store NULL values in the database.
  • IntegerField: For integer values.
  • PositiveIntegerField: An integer field that must be positive.
  • SmallIntegerField, BigIntegerField: Smaller and larger integer fields.
  • FloatField: For floating-point numbers.
  • DecimalField: For fixed-precision decimal numbers. Requires max_digits and decimal_places.
  • BooleanField: For boolean values (True/False).
  • NullBooleanField: A BooleanField that also accepts NULL.
  • DateField: For dates (YYYY-MM-DD).
  • DateTimeField: For dates and times (YYYY-MM-DD HH:MM:SS). auto_now_add=True sets the field to the current date/time when the object is created. auto_now=True updates the field every time the object is saved.
  • TimeField: For times (HH:MM:SS).
  • DurationField: Stores periods of time – modeled in Python by timedelta.
  • EmailField: A CharField that validates if the input is an email address.
  • URLField: A CharField that validates URLs.
  • FileField: For file uploads. Requires upload_to to specify the storage directory.
  • ImageField: For image uploads. Requires Pillow library and upload_to.
  • FilePathField: A CharField whose choices are limited to the filenames in a certain directory on the filesystem.
  • SlugField: A CharField intended to store a "slug" – a short label containing only letters, numbers, underscores or hyphens.
  • BinaryField: For storing raw binary data.
  • ForeignKey: For creating one-to-many relationships with other models. Requires on_delete to specify what happens when the related object is deleted (e.g., models.CASCADE, models.SET_NULL).
  • ManyToManyField: For creating many-to-many relationships.
  • OneToOneField: For creating one-to-one relationships.
  • GenericIPAddressField: For storing IPv4 or IPv6 addresses.
  • UUIDField: For storing universally unique identifiers.

1.2.3 Model Meta Options

  • ordering: Defines the default ordering of objects.
  • verbose_name: A human-readable name for the model.
  • verbose_name_plural: The plural form of the verbose name.
  • abstract = True: Makes the model an abstract base class.
  • db_table: Specifies the name of the database table.
  • unique_together: Defines a set of fields that, taken together, must be unique.
  • index_together: Defines a set of fields that should be indexed together.
  • get_latest_by: Specifies a field to use for retrieving the "latest" object.

1.2.4 Querying the Database

from .models import MyModel

# Get all objects
all_objects = MyModel.objects.all()

# Filter objects
filtered_objects = MyModel.objects.filter(name__contains='keyword', is_active=True)

# Get a single object by primary key
single_object = MyModel.objects.get(pk=1)

# Get a single object, handling DoesNotExist exception
from django.shortcuts import get_object_or_404
single_object = get_object_or_404(MyModel, pk=1)

# Create a new object
new_object = MyModel.objects.create(name='New Object', description='...')

# Update an existing object
obj = MyModel.objects.get(pk=1)
obj.name = 'Updated Name'
obj.save()

# Delete an object
obj = MyModel.objects.get(pk=1)
obj.delete()

# Complex lookups with Q objects
from django.db.models import Q
objects = MyModel.objects.filter(Q(name__startswith='A') | Q(description__icontains='data'))

# Ordering
ordered_objects = MyModel.objects.order_by('name', '-created_at')

# Limiting results
limited_objects = MyModel.objects.all()[:10]

# Chaining queries
chained_objects = MyModel.objects.filter(is_active=True).order_by('name')

1.2.5 Raw SQL Queries

from django.db import connection

def my_raw_query():
    with connection.cursor() as cursor:
        cursor.execute("SELECT * FROM myapp_mymodel WHERE name = %s", ['My Name'])
        row = cursor.fetchone()
        return row

1.3 Views

1.3.1 Create a View (views.py)

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, JsonResponse
from .models import MyModel

def my_view(request):
    data = MyModel.objects.all()  # Get all objects from MyModel
    context = {'data': data}
    return render(request, 'myapp/mytemplate.html', context)

def detail_view(request, pk):
    item = get_object_or_404(MyModel, pk=pk)
    return render(request, 'myapp/detail.html', {'item': item})

def json_response(request):
    data = {'message': 'Hello, world!'}
    return JsonResponse(data)

def http_response(request):
    return HttpResponse("<h1>Hello, world!</h1>", content_type="text/html")

1.3.2 Class-Based Views

from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import MyModel

class MyListView(ListView):
    model = MyModel
    template_name = 'myapp/mymodel_list.html'
    context_object_name = 'data'  # Renames the object_list in the template
    paginate_by = 10  # Enable pagination

class MyDetailView(DetailView):
    model = MyModel
    template_name = 'myapp/mymodel_detail.html'
    context_object_name = 'item'

class MyCreateView(CreateView):
    model = MyModel
    fields = ['name', 'description', 'is_active']  # Fields to include in the form
    template_name = 'myapp/mymodel_form.html'
    success_url = reverse_lazy('myapp:my_list_view')  # Redirect after successful creation

class MyUpdateView(UpdateView):
    model = MyModel
    fields = ['name', 'description', 'is_active']
    template_name = 'myapp/mymodel_form.html'
    success_url = reverse_lazy('myapp:my_list_view')

class MyDeleteView(DeleteView):
    model = MyModel
    template_name = 'myapp/mymodel_confirm_delete.html'
    success_url = reverse_lazy('myapp:my_list_view')

1.3.3 Function-Based View Decorators

  • @require_http_methods(["GET", "POST"]): Only allows specified HTTP methods.
  • @require_GET, @require_POST: Shorthand for requiring GET or POST.
  • @login_required: Requires the user to be logged in.
  • @permission_required('myapp.change_mymodel'): Requires the user to have a specific permission.
  • @staff_member_required: Requires the user to be a staff member.
  • @cache_page(60 * 15): Caches the view output for 15 minutes (requires cache configuration).

1.4 URLs

1.4.1 Define URL Patterns (urls.py)

Project urls.py:

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myapp/', include('myapp.urls', namespace='myapp')),  # Include app's URLs with namespace
]

App urls.py:

from django.urls import path
from . import views

app_name = 'myapp'  # App namespace

urlpatterns = [
    path('', views.my_view, name='my_view'),
    path('list/', views.MyListView.as_view(), name='my_list_view'),
    path('detail/<int:pk>/', views.MyDetailView.as_view(), name='my_detail_view'),
    path('create/', views.MyCreateView.as_view(), name='my_create_view'),
    path('update/<int:pk>/', views.MyUpdateView.as_view(), name='my_update_view'),
    path('delete/<int:pk>/', views.MyDeleteView.as_view(), name='my_delete_view'),
]

1.4.2 URL Reversing

In templates:

<a href="{% url 'myapp:my_detail_view' item.pk %}">{{ item.name }}</a>

In Python code:

from django.urls import reverse

url = reverse('myapp:my_detail_view', kwargs={'pk': 1})

1.5 Templates

1.5.1 Create a Template (mytemplate.html)

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Template{% endblock %}</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'myapp/css/style.css' %}">
</head>
<body>
    <header>
        <h1>{% block header %}My Website{% endblock %}</h1>
    </header>

    <main>
        {% block content %}
            <h1>Data from MyModel:</h1>
            <ul>
                {% for item in data %}
                    <li><a href="{% url 'myapp:my_detail_view' item.pk %}">{{ item.name }}</a> - {{ item.description }}</li>
                {% empty %}
                    <li>No data available.</li>
                {% endfor %}
            </ul>
        {% endblock %}
    </main>

    <footer>
        <p>&copy; 2025 My Website</p>
    </footer>
</body>
</html>

1.5.2 Template Inheritance

Create a base template (base.html):

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    <header>
        <h1>{% block header %}My Website{% endblock %}</h1>
    </header>

    <main>
        {% block content %}{% endblock %}
    </main>

    <footer>
        <p>&copy; 2025 My Website</p>
    </footer>
</body>
</html>

Extend the base template (mytemplate.html):

{% extends 'base.html' %}

{% block title %}My Custom Title{% endblock %}

{% block content %}
    <h1>Data from MyModel:</h1>
    <ul>
        {% for item in data %}
            <li>{{ item.name }} - {{ item.description }}</li>
        {% endfor %}
    </ul>
{% endblock %}

1.5.3 Template Tags and Filters

  • {{ variable }}: Outputs a variable.
  • {% tag %}: Template logic tag (e.g., for, if).
  • {{ variable|filter }}: Applies a filter to a variable.
  • {% load static %}: Loads the static template tag library for serving static files.
  • {% url 'view_name' arg1 arg2 %}: Reverses a URL pattern by its name.
  • {% csrf_token %}: Adds a CSRF token to a form.
  • {% now "Y-m-d H:i" %}: Displays the current date and time.
  • {% include "template_name.html" %}: Includes another template.
  • {% extends "base.html" %}: Extends a base template.
  • {% block block_name %}{% endblock %}: Defines a block for template inheritance.
  • {% if condition %}{% endif %}: Conditional logic.
  • {% for item in items %}{% endfor %}: Loop through a list.
  • {% with total=items|length %}: Assign a value to a variable within the template.

1.5.4 Common Template Filters

  • safe: Marks a string as safe for HTML output.
  • date:"FORMAT_STRING": Formats a date. See Django's documentation for format string options.
  • time:"FORMAT_STRING": Formats a time.
  • timesince: Displays the time elapsed since a date.
  • truncatechars:LENGTH: Truncates a string to a certain length.
  • truncatewords:NUM: Truncates a string to a certain number of words.
  • lower, upper: Converts a string to lowercase or uppercase.
  • title: Converts a string to title case.
  • capfirst: Capitalizes the first character of a string.
  • length: Returns the length of a value.
  • default:VALUE: Provides a default value if a variable is False.
  • filesizeformat: Formats a number as a human-readable file size.
  • stringformat:"E": Formats a number according to a string format specifier.
  • linebreaks: Replaces line breaks in plain text with appropriate HTML; a single newline becomes an HTML line break (<br>) and a new line surrounded by empty lines becomes a paragraph break (<p>).
  • urlencode: Encodes a string for use in a URL.
  • json_script: Safely outputs data as JSON for use in JavaScript.

1.6 Forms

1.6.1 Define a Form (forms.py)

from django import forms
from .models import MyModel

class MyForm(forms.Form):
    name = forms.CharField(label="Your Name", max_length=100,
                           widget=forms.TextInput(attrs={'class': 'form-control'}))
    email = forms.EmailField(label="Your Email",
                            widget=forms.EmailInput(attrs={'class': 'form-control'}))
    message = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}),
                              label="Your Message")
    agree = forms.BooleanField(label="I agree to the terms", required=True)

    # Custom validation
    def clean_name(self):
        name = self.cleaned_data['name']
        if len(name) < 3:
            raise forms.ValidationError("Name must be at least 3 characters long.")
        return name

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name', 'description', 'is_active']
        widgets = {
            'description': forms.Textarea(attrs={'rows': 4, 'cols': 40}),
        }
        labels = {
            'name': 'Model Name',
            'description': 'Model Description',
        }
        help_texts = {
            'name': 'Enter a descriptive name for the model.',
        }
        error_messages = {
            'name': {
                'required': 'Please enter a name.',
            },
        }

1.6.2 Form Fields

  • CharField: For text input.
  • IntegerField: For integer input.
  • FloatField: For floating-point input.
  • BooleanField: For checkbox input.
  • DateField, DateTimeField: For date and time input.
  • EmailField: For email input.
  • URLField: For URL input.
  • ChoiceField: For select input. Requires choices argument.
  • MultipleChoiceField: For multiple select input.
  • FileField: For file upload.
  • ImageField: For image upload.
  • ModelChoiceField: For selecting a model instance from a queryset.
  • ModelMultipleChoiceField: For selecting multiple model instances.
  • TypedChoiceField: Like ChoiceField, but coerces values to a specific type.
  • TypedMultipleChoiceField: Like MultipleChoiceField, but coerces values to a specific type.
  • RegexField: A CharField that validates against a regular expression.

1.6.3 Form Widgets

  • TextInput: Default text input.
  • Textarea: Multi-line text input.
  • NumberInput: For number input.
  • EmailInput: For email input.
  • URLInput: For URL input.
  • PasswordInput: For password input.
  • HiddenInput: A hidden input field.
  • Select: For single select dropdown.
  • SelectMultiple: For multiple select dropdown.
  • RadioSelect: For radio button selection.
  • CheckboxInput: For a single checkbox.
  • CheckboxSelectMultiple: For multiple checkboxes.
  • FileInput: For file uploads.
  • ClearableFileInput: A FileInput with a checkbox to clear the current file.
  • DateInput, DateTimeInput, TimeInput: For date, datetime, and time input, respectively.

1.6.4 Render a Form in a Template

<form method="post">
    {% csrf_token %}
    {% if form.errors %}
        <div class="alert alert-danger">
            Please correct the errors below.
        </div>
    {% endif %}
    {{ form.as_p }}  {# Renders the form as a series of <p> tags #}
    {# Or render fields individually: #}
    {# <div class="form-group">
        {{ form.name.label_tag }}
        {{ form.name }}
        {{ form.name.errors }}
    </div> #}
    <button type="submit">Submit</button>
</form>

1.6.5 Process Form Data in a View

from django.shortcuts import render, redirect
from .forms import MyForm, MyModelForm

def my_form_view(request):
    if request.method == 'POST':
        form = MyForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            # Process the data (e.g., save to database, send email)
            return redirect('success_url')  # Redirect to a success page
        else:
            # Form is invalid, display errors
            return render(request, 'myapp/myform.html', {'form': form})
    else:
        form = MyForm()
    return render(request, 'myapp/myform.html', {'form': form})

def my_model_form_view(request):
    if request.method == 'POST':
        form = MyModelForm(request.POST, request.FILES) # Include request.FILES for file uploads
        if form.is_valid():
            instance = form.save()  # Save the model instance
            # Or, to process data before saving:
            # new_instance = form.save(commit=False)
            # new_instance.some_field = 'some_value'
            # new_instance.save()
            return redirect('my_list_view')
        else:
            return render(request, 'myapp/mymodel_form.html', {'form': form})
    else:
        form = MyModelForm()
    return render(request, 'myapp/mymodel_form.html', {'form': form})

1.7 Admin Interface

1.7.1 Register a Model (admin.py)

from django.contrib import admin
from .models import MyModel

admin.site.register(MyModel)

1.7.2 Customize Admin Interface

from django.contrib import admin
from .models import MyModel

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'created_at', 'is_active')  # Columns to display in list view
    search_fields = ('name', 'description') # Enable search
    list_filter = ('is_active', 'created_at')          # Enable filtering
    ordering = ('name',)
    readonly_fields = ('created_at', 'updated_at')
    date_hierarchy = 'created_at' # Drill-down by date
    prepopulated_fields = {'slug': ('name',)} # Automatically populate slug field
    raw_id_fields = ('related_model',) # Use raw ID lookup for ForeignKey/ManyToManyField
    filter_horizontal = ('many_to_many_field',) # Use horizontal filter for ManyToManyField
    filter_vertical = ('another_many_to_many_field',) # Use vertical filter for ManyToManyField
    fieldsets = (
        (None, {
            'fields': ('name', 'description')
        }),
        ('Advanced options', {
            'classes': ('collapse',),
            'fields': ('is_active', 'order'),
        }),
    )
    actions = ['make_active', 'make_inactive']

    def make_active(self, request, queryset):
        queryset.update(is_active=True)
    make_active.short_description = "Mark selected entries as active"

    def make_inactive(self, request, queryset):
        queryset.update(is_active=False)
    make_inactive.short_description = "Mark selected entries as inactive"

1.7.3 Inline Admin

from django.contrib import admin
from .models import MyModel, RelatedModel

class RelatedModelAdminInline(admin.TabularInline):  # Or admin.StackedInline
    model = RelatedModel
    extra = 1  # Number of empty forms to display
    fk_name = 'mymodel' # Specify the ForeignKey field name in RelatedModel

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    inlines = [RelatedModelAdminInline]

1.8 Settings (settings.py)

1.8.1 Key Settings

  • DEBUG = True: Enables debug mode (for development only!).
  • SECRET_KEY: A secret key for security. Never share this! Use environment variables.
  • ALLOWED_HOSTS = ['*']: List of allowed hostnames for the Django project. In production, set this to your domain name.
  • INSTALLED_APPS: List of installed Django apps.
  • MIDDLEWARE: List of enabled middleware.
  • ROOT_URLCONF: Specifies the root URL configuration module.
  • DATABASES: Database connection settings.
  • STATIC_URL: URL to serve static files.
  • STATIC_ROOT: The absolute path to the directory where collectstatic will collect static files for production.
  • STATICFILES_DIRS: List of directories where Django will look for static files.
  • MEDIA_URL: URL to serve media files (user-uploaded files).
  • MEDIA_ROOT: The absolute path to the directory where user-uploaded media files will be stored.
  • TEMPLATES: Template engine settings.
  • LANGUAGE_CODE: The default language code for the project.
  • TIME_ZONE: The timezone for the project.
  • USE_I18N = True: Enables internationalization.
  • USE_L10N = True: Enables localization.
  • USE_TZ = True: Enables timezone support.
  • DEFAULT_AUTO_FIELD: Default auto-field type for primary keys (Django 3.2+).
  • SESSION_ENGINE: Defines the session storage engine.
  • CSRF_COOKIE_SECURE = True: Ensures the CSRF cookie is only sent over HTTPS (production).
  • SESSION_COOKIE_SECURE = True: Ensures the session cookie is only sent over HTTPS (production).
  • SECURE_SSL_REDIRECT = True: Redirects all HTTP traffic to HTTPS (production).
  • SECURE_HSTS_SECONDS = 31536000: Enables HTTP Strict Transport Security (HSTS) (production).
  • SECURE_HSTS_INCLUDE_SUBDOMAINS = True: Includes subdomains in HSTS policy (production).
  • SECURE_HSTS_PRELOAD = True: Enables HSTS preloading (production).

1.8.2 Database Configuration

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

1.8.3 Static Files Configuration

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'myapp/static'),
]

1.8.4 Middleware Configuration

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware', # Add for caching
    'django.middleware.cache.FetchFromCacheMiddleware', # Add for caching
]

1.8.5 Caching Configuration

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
    }
}

CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 600  # Cache for 10 minutes
CACHE_MIDDLEWARE_KEY_PREFIX = ''

1.8.6 Email Configuration

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your_email@gmail.com'
EMAIL_HOST_PASSWORD = 'your_password'
DEFAULT_FROM_EMAIL = 'your_email@gmail.com'

1.9 Common Commands

  • python manage.py runserver: Starts the development server.
  • python manage.py shell: Opens a Python shell with Django environment loaded.
  • python manage.py createsuperuser: Creates an admin user.
  • python manage.py makemigrations: Creates new migrations based on model changes.
  • python manage.py migrate: Applies migrations to the database.
  • python manage.py collectstatic: Collects static files into STATIC_ROOT.
  • python manage.py test: Runs the project's tests.
  • python manage.py dbshell: Opens a shell for the database.
  • python manage.py dumpdata: Exports data from the database as JSON or XML.
  • python manage.py loaddata: Loads data from a JSON or XML fixture into the database.
  • python manage.py check: Performs system checks to identify potential problems.
  • python manage.py showmigrations: Shows the status of migrations.
  • python manage.py inspectdb: Generates models from an existing database.
  • python manage.py flush: Empties the database.
  • python manage.py changepassword <username>: Changes a user's password.

1.10 Django REST Framework (DRF)

1.10.1 Installation

pip install djangorestframework

Add 'rest_framework' to INSTALLED_APPS in settings.py.

1.10.2 Serializers (serializers.py)

from rest_framework import serializers
from .models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'  # Or specify a tuple of field names
        # or exclude = ('field1', 'field2')
        read_only_fields = ('created_at', 'updated_at') # Make fields read-only

    # Custom field validation
    def validate_name(self, value):
        if len(value) < 5:
            raise serializers.ValidationError("Name must be at least 5 characters long.")
        return value

    # Object-level validation
    def validate(self, data):
        if data['name'] == data['description']:
            raise serializers.ValidationError("Name and description cannot be the same.")
        return data

1.10.3 Views (views.py)

from rest_framework import generics, permissions, status
from rest_framework.response import Response
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelList(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly] # Require authentication for write operations

    def perform_create(self, serializer):
        serializer.save() # Save the object

class MyModelDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def delete(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT) # Return 204 No Content on successful deletion

1.10.4 URLs (urls.py)

from django.urls import path
from . import views

urlpatterns = [
    path('mymodel/', views.MyModelList.as_view(), name='mymodel-list'),
    path('mymodel/<int:pk>/', views.MyModelDetail.as_view(), name='mymodel-detail'),
]

1.10.5 Authentication and Permissions

  • permissions.AllowAny: Allows access to anyone, authenticated or not.
  • permissions.IsAuthenticated: Only allows access to authenticated users.
  • permissions.IsAdminUser: Only allows access to admin users.
  • permissions.IsAuthenticatedOrReadOnly: Allows read access to anyone, but write access only to authenticated users.
  • Custom permissions: You can create custom permission classes to define more specific access control rules.

1.10.6 APIView

For more control, use APIView:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import MyModel
from .serializers import MyModelSerializer

class MyCustomAPIView(APIView):
    def get(self, request):
        data = MyModel.objects.all()
        serializer = MyModelSerializer(data, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = MyModelSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

1.11 Security

1.11.1 CSRF Protection

  • Use the {% csrf_token %} template tag in forms.
  • Ensure django.middleware.csrf.CsrfViewMiddleware is in MIDDLEWARE.

1.11.2 SQL Injection

  • Use Django's ORM to avoid raw SQL queries whenever possible.
  • If you must use raw SQL, use parameterized queries to escape user input.

1.11.3 XSS (Cross-Site Scripting)

  • Use the safe template filter with caution. Only use it on data you trust.
  • Sanitize user input before displaying it.

1.11.4 Clickjacking

  • Ensure django.middleware.clickjacking.XFrameOptionsMiddleware is in MIDDLEWARE.
  • Set X_FRAME_OPTIONS = 'DENY' or X_FRAME_OPTIONS = 'SAMEORIGIN' in settings.py.

1.11.5 Security Headers

Use django-security or similar package to set security headers.

1.11.6 HTTPS

  • Configure your web server to use HTTPS.
  • Set SECURE_SSL_REDIRECT = True in settings.py to redirect HTTP requests to HTTPS.
  • Set SECURE_HSTS_SECONDS and SECURE_HSTS_INCLUDE_SUBDOMAINS for HTTP Strict Transport Security.
  • Set SECURE_HSTS_PRELOAD = True to enable HSTS preloading.

1.11.7 Authentication

Use Django's built-in authentication

import TestCase
from .models import MyModel

class MyModelTest(TestCase):
    def setUp(self):
        MyModel.objects.create(name='Test Object', description='Test Description')

    def test_model_content(self):
        obj = MyModel.objects.get(name='Test Object')
        self.assertEqual(obj.description, 'Test Description')

1.11.8 Test Client

from django.test import Client

class MyViewTest(TestCase):
    def setUp(self):
        self.client = Client()

    def test_my_view(self):
        response = self.client.get('/myapp/')
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'My Template')

1.12 Deployment

1.12.1 Production Settings

Create a production.py settings file:

from .settings import *

DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

1.12.2 Web Server (Gunicorn)

Install Gunicorn:

pip install gunicorn

Run Gunicorn:

gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

1.12.3 Process Manager (systemd)

Create a systemd service file (/etc/systemd/system/myproject.service):

[Unit]
Description=My Django Project
After=network.target

[Service]
User=myuser
Group=mygroup
WorkingDirectory=/path/to/myproject
ExecStart=/path/to/venv/bin/gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl enable myproject
sudo systemctl start myproject

1.12.4 Static Files

  • Run python manage.py collectstatic to collect static files.
  • Configure your web server (e.g., Nginx, Apache) to serve static files from STATIC_ROOT.

1.12.5 Media Files

  • Configure your web server to serve media files from MEDIA_ROOT.
  • Consider using a cloud storage service (e.g., AWS S3) for media files.

1.12.6 Database

  • Use a production-ready database (e.g., PostgreSQL, MySQL).
  • Configure the database connection settings in settings.py.
  • Back up your database regularly.

1.12.7 Environment Variables

  • Use environment variables for sensitive settings (e.g., SECRET_KEY, database credentials).
  • Use a package like python-dotenv to manage environment variables.

1.13 Caching

1.13.1 Per-Site Cache

Add django.middleware.cache.UpdateCacheMiddleware and django.middleware.cache.FetchFromCacheMiddleware to MIDDLEWARE in settings.py.

# settings.py
MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    # ... other middleware ...
    'django.middleware.cache.FetchFromCacheMiddleware',
]

Configure the cache backend:

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',  # Example using Redis
    }
}

CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 600  # Cache for 10 minutes
CACHE_MIDDLEWARE_KEY_PREFIX = ''

1.13.2 Per-View Cache

Use the @cache_page decorator:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)  # Cache for 15 minutes
def my_view(request):
    # ...
    return render(request, 'myapp/mytemplate.html', context)

1.13.3 Template Fragment Caching

{% load cache %}

{% cache 600 "my_template_fragment" %}
    {# Expensive template code here #}
{% endcache %}

1.13.4 Low-Level Cache API

from django.core.cache import cache

# Set a value
cache.set('my_key', 'my_value', 600)  # Cache for 10 minutes

# Get a value
value = cache.get('my_key')

# Delete a value
cache.delete('my_key')

1.14 Signals

1.14.1 Define a Signal (signals.py)

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

@receiver(post_save, sender=MyModel)
def my_model_post_save(sender, instance, created, **kwargs):
    if created:
        # Perform actions when a new MyModel instance is created
        print(f"New MyModel instance created: {instance.name}")
    else:
        # Perform actions when a MyModel instance is updated
        print(f"MyModel instance updated: {instance.name}")

1.14.2 Connect Signals (apps.py)

from django.apps import AppConfig

class MyappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'myapp'

    def ready(self):
        import myapp.signals  # Import the signals module

1.14.3 Common Signals

  • pre_save, post_save: Sent before and after a model's save() method is called.
  • pre_delete, post_delete: Sent before and after a model instance is deleted.
  • m2m_changed: Sent when a ManyToManyField is changed.
  • pre_migrate, post_migrate: Sent before and after migrations are applied.

1.15 Internationalization (i18n) and Localization (l10n)

1.15.1 Enable i18n and l10n

Set USE_I18N = True and USE_L10N = True in settings.py.

1.15.2 Set the Language Code

Set LANGUAGE_CODE = 'en-us' in settings.py.

1.15.3 Translate Strings

In Python code:

from django.utils.translation import gettext as _

def my_view(request):
    message = _("Hello, world!")
    return render(request, 'myapp/mytemplate.html', {'message': message})

In templates:

{% load i18n %}
<h1>{% trans "Hello, world!" %}</h1>

1.15.4 Mark Strings for Translation

Use makemessages command:

python manage.py makemessages -l de  # Create a translation file for German

1.15.5 Translate Strings with Context

from django.utils.translation import pgettext as _

message = _("context", "Hello, world!")

1.15.6 Pluralization

from django.utils.translation import ngettext

def my_view(request, count):
    message = ngettext(
        'There is %(count)d object',
        'There are %(count)d objects',
        count
    ) % {'count': count}
    return render(request, 'myapp/mytemplate.html', {'message': message})

1.15.7 Switch Language

<form action="{% url 'set_language' %}" method="post">
    {% csrf_token %}
    <input name="language" type="hidden" value="de">
    <button type="submit">Switch to German</button>
</form>

1.16 Custom Management Commands

1.16.1 Create a Command (management/commands/mycommand.py)

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'My custom command'

    def add_arguments(self, parser):
        parser.add_argument('argument', nargs='?', type=str, help='An argument for the command')

    def handle(self, *args, **options):
        argument = options['argument']
        self.stdout.write(self.style.SUCCESS(f'Successfully executed mycommand with argument: {argument}'))

1.16.2 Run the Command

python manage.py mycommand "My Argument"

1.17 Middleware

1.17.1 Create a Middleware (middleware.py)

class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before the view (pre-processing)
        print("Before view")

        response = self.get_response(request)

        # Code to be executed for each request after the view (post-processing)
        print("After view")

        return response

1.17.2 Activate Middleware

Add the middleware to MIDDLEWARE in settings.py:

MIDDLEWARE = [
    # ...
    'myapp.middleware.MyMiddleware',
]

1.18 File Handling

1.18.1 Uploading Files

In forms.py:

class UploadFileForm(forms.Form):
    file = forms.FileField()

In views.py:

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            uploaded_file = request.FILES['file']
            # Process the uploaded file (e.g., save to MEDIA_ROOT)
            with open(os.path.join(settings.MEDIA_ROOT, uploaded_file.name), 'wb+') as destination:
                for chunk in uploaded_file.chunks():
                    destination.write(chunk)
            return HttpResponse("File uploaded successfully")
    else:
        form = UploadFileForm()
    return render(request, 'myapp/upload.html', {'form': form})

In templates/myapp/upload.html:

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Upload</button>
</form>

1.18.2 Serving Files

Configure MEDIA_URL and MEDIA_ROOT in settings.py.

In urls.py:

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

urlpatterns = [
    # ... your other URL patterns ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

1.19 Logging

1.19.1 Configure Logging (settings.py)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': os.path.join(BASE_DIR, 'debug.log'),
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'level': 'INFO',
        },
    },
}

1.19.2 Use Logging

import logging

logger = logging.getLogger(__name__)

def my_view(request):
    logger.info("My view was accessed")
    try:
        # ... some code that might raise an exception ...
    except Exception as e:
        logger.exception("An error occurred")

1.20 Django Channels (Asynchronous)

1.20.1 Installation

pip install channels

1.20.2 Configure Channels (settings.py)

ASGI_APPLICATION = 'myproject.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

1.20.3 Create a Consumer (consumers.py)

from channels.generic.websocket import WebsocketConsumer
import json

class MyConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        self.send(text_data=json.dumps({
            'message': message
        }))

1.20.4 Configure Routing (routing.py)

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/myapp/$', consumers.MyConsumer.as_asgi()),
]

1.20.5 Update ASGI Application (asgi.py)

import os

from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myapp.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            myapp.routing.websocket_urlpatterns
        )
    ),
})

1.21 Django Allauth (Authentication)

1.21.1 Installation

pip install django-allauth

1.21.2 Configuration (settings.py)

INSTALLED_APPS = [
    # ...
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    # ... include providers you want to use ...
    # 'allauth.socialaccount.providers.google',
]

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

SITE_ID = 1

LOGIN_REDIRECT_URL = '/'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'

1.21.3 URLs (urls.py)

from django.urls import include, path

urlpatterns = [
    path('accounts/', include('allauth.urls')),
]

1.21.4 Templates

Use Allauth's template tags and forms for registration, login, etc.

1.22 Django Debug Toolbar

1.22.1 Installation

pip install django-debug-toolbar

1.22.2 Configuration (settings.py)

INSTALLED_APPS = [
    # ...
    'debug_toolbar',
]

MIDDLEWARE = [
    # ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]

INTERNAL_IPS = [
    '127.0.0.1',
]

1.22.3 URLs (urls.py)

from django.urls import include, path

urlpatterns = [
    # ...
]

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [
        path('__debug__/', include(debug_toolbar.urls)),
    ]

1.23 Tips and Best Practices

  • Use virtual environments to isolate project dependencies.
  • Keep SECRET_KEY secure and out of your codebase. Use environment variables.
  • Use meaningful names for models, views, and URLs.
  • Follow the DRY (Don't Repeat Yourself) principle.
  • Write unit tests to ensure code quality.
  • Use Django's built-in security features (e.g., CSRF protection).
  • Configure static file serving correctly in production.
  • Use a production-ready web server (e.g., Gunicorn, uWSGI) and a process manager (e.g., Supervisor, systemd) for deployment.
  • Use a linter (like flake8) and formatter (like black) to ensure consistent code style.
  • Use a well-defined project structure.
  • Keep your code modular and reusable.
  • Document your code.
  • Use a version control system (e.g., Git).
  • Follow Django's coding style guidelines.
  • Use Django's built-in caching mechanisms to improve performance.
  • Monitor your application for errors and performance issues.
  • Use a CDN (Content Delivery Network) for static files.
  • Optimize database queries.
  • Use asynchronous tasks for long-running operations (e.g., sending emails).
  • Implement proper logging and error handling.
  • Regularly update Django and its dependencies.
  • Use a security scanner to identify potential vulnerabilities.
  • Follow security best practices.