Install Now

django/django

Django Web Framework

Last updated on Dec 17, 2025 (Commit: 4702b36)

Overview

Relevant Files
  • django/init.py
  • django/conf/init.py
  • pyproject.toml
  • README.rst

Django is a high-level Python web framework designed for rapid development and clean, pragmatic design. This repository contains Django 6.1 (alpha), a full-featured framework for building web applications with Python 3.12+.

Core Architecture

Django follows a modular, layered architecture that separates concerns across distinct components:

Loading diagram...

Key Components

Apps & Configuration (django/apps, django/conf)

  • The app registry system manages installed applications and their lifecycle
  • Settings are lazily loaded via LazySettings, supporting both environment variables and programmatic configuration
  • Each app can define models, views, templates, and middleware

Database Layer (django/db)

  • Object-relational mapping (ORM) for database interactions
  • Support for multiple databases and query optimization
  • Migration system for schema management

HTTP & Views (django/http, django/views)

  • Request/response handling through WSGI and ASGI interfaces
  • Class-based and function-based views for request processing
  • Middleware hooks for cross-cutting concerns

Forms & Validation (django/forms)

  • HTML form generation and validation
  • Field types with built-in error handling
  • Model form integration for database-backed forms

Templates (django/template)

  • Django Template Language (DTL) for rendering HTML
  • Template inheritance and reusable components
  • Context processors for injecting data into templates

URL Routing (django/urls)

  • Pattern-based URL configuration
  • Named URL reversing for dynamic link generation
  • Include mechanism for modular URL organization

Middleware (django/middleware)

  • Security middleware (CSRF, XFrame options)
  • Session and authentication middleware
  • Custom middleware for application-specific logic

Setup & Initialization

Django initialization happens through the setup() function in django/__init__.py:

django.setup()  # Configures settings, logging, and populates app registry

This single call triggers:

  1. Settings configuration from DJANGO_SETTINGS_MODULE environment variable
  2. Logging setup based on SETTINGS.LOGGING_CONFIG
  3. App registry population from INSTALLED_APPS

Project Structure

A typical Django project includes:

  • Apps: Reusable Python packages containing models, views, and templates
  • Settings: Configuration module specifying installed apps, middleware, and database connections
  • URLs: Root URL configuration routing requests to views
  • Static/Media: Asset directories for CSS, JavaScript, and user uploads

Dependencies

Django requires Python 3.12+ and has minimal core dependencies:

  • asgiref (3.9.1+) for async support
  • sqlparse (0.5.0+) for SQL parsing
  • tzdata (Windows only) for timezone data

Optional dependencies include argon2-cffi and bcrypt for password hashing.

Architecture & Request/Response Cycle

Relevant Files
  • django/core/handlers/base.py
  • django/core/handlers/wsgi.py
  • django/core/handlers/asgi.py
  • django/core/handlers/exception.py
  • django/urls/resolvers.py
  • django/core/signals.py

Overview

Django's request/response cycle is the core flow that transforms incoming HTTP requests into responses. The architecture supports both synchronous (WSGI) and asynchronous (ASGI) request handling, with a unified middleware chain that wraps the entire process.

Loading diagram...

Request Entry Points

Django provides two handler classes for different server types:

WSGIHandler (django/core/handlers/wsgi.py): Handles traditional WSGI servers. The __call__ method receives environ and start_response, creates a WSGIRequest object, and returns the response.

ASGIHandler (django/core/handlers/asgi.py): Handles async ASGI servers. The __call__ method is async and receives scope, receive, and send. It reads the request body asynchronously and manages concurrent operations.

Both handlers inherit from BaseHandler and follow the same core flow after request creation.

Middleware Chain Architecture

The middleware chain is built during handler initialization via load_middleware(). Middleware is loaded in reverse order from settings.MIDDLEWARE, creating a nested callable stack:

handler = convert_exception_to_response(get_response)
for middleware_path in reversed(settings.MIDDLEWARE):
    middleware = import_string(middleware_path)
    mw_instance = middleware(adapted_handler)
    handler = convert_exception_to_response(mw_instance)

This creates a chain where each middleware wraps the next, allowing request preprocessing and response postprocessing. The convert_exception_to_response wrapper ensures exceptions are converted to HTTP responses at each layer.

Request Resolution & View Dispatch

After middleware processing, _get_response() (or _get_response_async()) resolves the URL and executes the view:

  1. URL Resolution: resolve_request() uses the URL resolver to match request.path_info against patterns in ROOT_URLCONF, returning a ResolverMatch object with the view callable and arguments.

  2. View Middleware: process_view hooks are called with the resolved view and arguments. If any returns a response, view execution is skipped.

  3. View Execution: The view is wrapped with make_view_atomic() for database transaction handling, then called with the request and resolved arguments.

  4. Template Response Middleware: If the response has a render() method, process_template_response hooks are applied before rendering.

Exception Handling

Exceptions are caught at multiple levels:

  • Middleware-level: convert_exception_to_response wraps each middleware to catch exceptions and convert them to responses.
  • View-level: Exceptions from view execution are passed to process_exception_by_middleware().
  • Exception Middleware: Registered process_exception hooks can handle or transform exceptions.

The response_for_exception() function maps exception types to appropriate HTTP responses (404 for Http404, 403 for PermissionDenied, etc.).

Async/Sync Adaptation

Django supports mixing sync and async middleware/views via adapt_method_mode():

  • Sync middleware with async handlers: Wrapped with sync_to_async(thread_sensitive=True)
  • Async middleware with sync handlers: Wrapped with async_to_sync()

This allows gradual async adoption without requiring all components to be async-compatible.

Signal Lifecycle

Two key signals bracket the request cycle:

  • request_started: Sent after handler initialization, before middleware processing
  • request_finished: Sent after response completion, triggering reset_urlconf() to clean up thread-local state

These signals enable logging, monitoring, and cleanup operations.

Models & ORM

Relevant Files
  • django/db/models/init.py
  • django/db/models/base.py
  • django/db/models/fields/init.py
  • django/db/models/query.py
  • django/db/models/manager.py
  • django/db/migrations/init.py

Django's ORM (Object-Relational Mapping) is the core abstraction layer that maps Python classes to database tables. It provides a high-level, Pythonic interface for database operations without writing raw SQL.

Core Architecture

The ORM consists of four primary components working together:

Model (django/db/models/base.py): The foundation of the ORM. Each model is a Python class inheriting from Model that represents a database table. The ModelBase metaclass handles model initialization, field registration, and metadata setup. Models define fields as class attributes, which automatically map to database columns.

Fields (django/db/models/fields/__init__.py): Field instances represent database columns. Django provides built-in field types like CharField, IntegerField, ForeignKey, and DateTimeField. Each field knows how to convert Python values to database-specific types and vice versa through methods like get_prep_value() and from_db_value().

Manager (django/db/models/manager.py): The gateway to database queries. Every model has a default objects manager (an instance of Manager). Managers provide methods like all(), filter(), and create() that return QuerySet instances. Custom managers can be created by subclassing Manager to add domain-specific query methods.

QuerySet (django/db/models/query.py): Represents a lazy database lookup. QuerySets are chainable—calling filter methods returns new QuerySet instances without executing queries. The actual database query executes only when the QuerySet is evaluated (iteration, slicing, or calling list()).

Query Execution Flow

# QuerySet is lazy—no database hit yet
users = User.objects.filter(active=True)

# Query executes here when iterating
for user in users:
    print(user.name)

The flow: Manager.all()QuerySet instance → filter() chains → SQL generation → Database execution.

Field Relationships

Django handles three main relationship types through special field classes:

  • ForeignKey: One-to-many relationship. Creates a database foreign key constraint.
  • OneToOneField: One-to-one relationship. Enforces uniqueness on the foreign key.
  • ManyToManyField: Many-to-many relationship. Creates an intermediate join table automatically.

Reverse relationships are automatically created, allowing queries from both sides (e.g., author.book_set.all()).

Migrations System

The django/db/migrations/ module handles schema versioning. Migrations are Python files that describe database changes. The system tracks applied migrations and can roll forward or backward. Custom migration operations can be defined for complex schema transformations.

Key Design Patterns

Lazy Evaluation: QuerySets defer database queries until necessary, enabling efficient query optimization and chaining.

Descriptor Protocol: Fields use Python descriptors to intercept attribute access on model instances, enabling custom behavior like lazy loading of related objects.

Metaclass Magic: ModelBase processes field definitions at class creation time, registering fields and setting up model metadata without requiring explicit registration calls.

Views & URL Routing

Relevant Files
  • django/views/generic/base.py
  • django/views/generic/init.py
  • django/urls/conf.py
  • django/urls/base.py
  • django/urls/resolvers.py
  • django/http/request.py
  • django/http/response.py

Django's views and URL routing system connects HTTP requests to Python functions or class-based views. This section explains how requests flow through URL patterns to views, and how views process requests and return responses.

Core View Architecture

The foundation is the View class, a simple parent for all views that implements HTTP method dispatching. When a request arrives, View.dispatch() routes it to the appropriate HTTP method handler (get(), post(), etc.). The as_view() class method converts a view class into a callable that can be used in URL patterns.

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

class MyView(View):
    def get(self, request, *args, **kwargs):
        return HttpResponse("Hello, World!")

Generic views extend this base with common patterns. TemplateView renders templates, RedirectView handles redirects, and specialized views like ListView and DetailView handle database queries and pagination.

URL Routing System

URL patterns are defined in urlpatterns lists using path() or re_path() functions. The path() function uses a simpler syntax with angle-bracket converters, while re_path() uses regular expressions.

from django.urls import path, include
from . import views

urlpatterns = [
    path("articles/<int:pk>/", views.article_detail, name="article-detail"),
    path("blog/", include("blog.urls")),
]

Built-in converters include int, str, slug, uuid, and path. Custom converters can be registered via register_converter().

Request Resolution and Matching

When a request arrives, Django's URL resolver matches the path against patterns in order. The RoutePattern class converts path syntax to regex, then uses match() to extract captured parameters. Converters transform captured strings to Python types (e.g., &lt;int:pk&gt; converts to an integer).

The resolve() function returns a ResolverMatch object containing the matched view, arguments, and keyword arguments. The reverse() function does the opposite: it generates URLs from view names and arguments.

Request and Response Objects

Every view receives an HttpRequest object containing metadata: method, GET, POST, FILES, META, path, and headers. Views return HttpResponse objects or subclasses like TemplateResponse, JsonResponse, or FileResponse.

View Mixins and Composition

Django uses mixins for code reuse. ContextMixin provides get_context_data(), TemplateResponseMixin handles template rendering, and SingleObjectMixin or MultipleObjectMixin manage database queries. Views combine these mixins to build functionality.

from django.views.generic import ListView
from .models import Article

class ArticleListView(ListView):
    model = Article
    paginate_by = 10

Request Flow Diagram

Loading diagram...

Key Concepts

  • URL Patterns: Declarative mappings from URL paths to views
  • Converters: Type-safe parameter extraction from URLs
  • Dispatch: HTTP method routing within views
  • Mixins: Reusable view functionality via multiple inheritance
  • Reverse Resolution: Generate URLs from view names programmatically

Forms & Validation

Relevant Files
  • django/forms/forms.py
  • django/forms/fields.py
  • django/forms/widgets.py
  • django/forms/models.py
  • django/core/validators.py

Django's forms system provides a declarative way to define, render, and validate HTML forms. Forms separate data validation logic from presentation, making it easy to reuse validation across different interfaces.

Core Architecture

The forms system consists of three main layers:

  1. Fields (django/forms/fields.py) - Handle data validation and type conversion
  2. Widgets (django/forms/widgets.py) - Render HTML input elements
  3. Forms (django/forms/forms.py) - Orchestrate fields and manage the validation lifecycle
Loading diagram...

Field Validation Pipeline

When a form is submitted, validation follows a three-step process per field:

  1. to_python() - Converts raw input to Python type (e.g., string to integer)
  2. validate() - Checks required status and field-specific rules
  3. run_validators() - Executes custom validators from the validators list
def clean(self, value):
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value

Form-Level Validation

The full_clean() method orchestrates the complete validation workflow:

def full_clean(self):
    self._clean_fields()      # Validate each field individually
    self._clean_form()        # Call form.clean() for cross-field validation
    self._post_clean()        # Hook for model validation (ModelForm)

Field errors are collected in self._errors, and cleaned values go into self.cleaned_data. Call form.is_valid() to check if validation passed.

Common Field Types

Django provides built-in fields for common data types:

  • CharField - Text input with optional max/min length
  • IntegerField - Whole numbers with optional min/max value
  • EmailField - Email validation using regex
  • DateField - Date parsing with configurable input formats
  • ChoiceField - Dropdown selection with validation against choices
  • FileField - File upload handling
  • BooleanField - Checkbox input

Each field has a default widget and error messages. Override default_error_messages to customize validation error text.

Validators

Validators are callable objects that raise ValidationError if validation fails. Django provides built-in validators in django.core.validators:

  • RegexValidator - Pattern matching
  • EmailValidator - Email format validation
  • URLValidator - URL format validation
  • MaxLengthValidator, MinLengthValidator - String length constraints
  • MaxValueValidator, MinValueValidator - Numeric bounds

Add custom validators to a field via the validators parameter:

from django.core.validators import RegexValidator

field = CharField(
    validators=[RegexValidator(r'^[A-Z]+$', 'Only uppercase letters')]
)

Widgets and Rendering

Widgets handle HTML rendering and data extraction. Each field has a default widget (e.g., CharField uses TextInput). Override via the widget parameter:

field = CharField(widget=Textarea(attrs={'rows': 4}))

Widgets implement render() to produce HTML and value_from_datadict() to extract submitted data. The get_context() method prepares data for template rendering.

ModelForm Integration

ModelForm automatically generates form fields from model fields. It calls Model.full_clean() during form validation via the _post_clean() hook, ensuring model-level constraints are enforced.

Templates & Rendering

Relevant Files
  • django/template/base.py
  • django/template/engine.py
  • django/template/loader.py
  • django/template/context.py
  • django/template/backends/django.py

Django's template system is built on a pluggable backend architecture that supports multiple template engines (Django's native language, Jinja2, etc.). The core flow involves loading, parsing, and rendering templates with a context.

Architecture Overview

Loading diagram...

Key Components

Engine (django.template.engine.Engine) is the core orchestrator. It manages template directories, loaders, context processors, and built-in template tags/filters. When you call engine.get_template(name), it searches through configured loaders to find and compile the template.

Template (django.template.base.Template) represents a compiled template. During initialization, it tokenizes the template string using a Lexer, then parses tokens into a NodeList of executable nodes. The render() method executes this node tree with a given context.

Loaders find template files on disk. The default chain uses filesystem.Loader (searches TEMPLATES[DIRS]) and optionally app_directories.Loader (searches app/templates/ in installed apps). A cached.Loader wrapper caches compiled templates for performance.

Context (django.template.context.Context) is a stack of dictionaries holding template variables. RequestContext extends this by automatically running context processors (functions that inject request-specific data like CSRF tokens). Variables are resolved by searching the stack from top to bottom.

Rendering Pipeline

  1. Load: loader.get_template(name) or loader.render_to_string(name, context) initiates the process
  2. Find: Engine iterates through loaders to locate the template file
  3. Parse: Lexer tokenizes the template string into TEXT, VAR, BLOCK, and COMMENT tokens
  4. Compile: Parser converts tokens into a tree of Node objects (TextNode, VariableNode, IfNode, ForNode, etc.)
  5. Render: Template.render() executes the node tree, with each node calling its render() method recursively

Backend Abstraction

DjangoTemplates (in backends/django.py) wraps the native Engine to conform to Django's template backend API. This allows swapping engines via the TEMPLATES setting. Each backend provides get_template(), from_string(), and render_to_string() methods with a consistent interface.

Context Processors

Context processors are callables that receive a request and return a dictionary. RequestContext automatically runs configured processors during initialization, injecting their output into the context stack. This pattern enables reusable context data (e.g., CSRF tokens, user info) across all templates.

Contrib Packages & Extensions

Relevant Files
  • django/contrib/admin/sites.py
  • django/contrib/auth/models.py
  • django/contrib/sessions/models.py
  • django/contrib/staticfiles/finders.py
  • django/contrib/contenttypes/models.py

Django's contrib packages provide a collection of optional, reusable applications that solve common web development problems. These packages follow Django's "batteries included" philosophy and are designed to be modular, allowing developers to include only what they need.

Core Contrib Packages

Admin (django.contrib.admin) provides an automatically generated administrative interface for managing models. It requires both auth and contenttypes to be installed. The AdminSite class encapsulates the admin application and manages model registration through the register() method. Developers can customize the admin by subclassing ModelAdmin and overriding template paths, form classes, and view methods.

Auth (django.contrib.auth) implements Django's authentication and authorization framework. It provides the User model, Permission model (linked to ContentType), and Group model for managing user access. The framework includes password hashing, permission checking, and signal handlers that automatically create permissions during migrations.

ContentTypes (django.contrib.contenttypes) provides a lightweight framework for tracking all installed models in the database. The ContentType model stores app labels and model names, enabling generic relations. It's used by auth (for permissions), admin (for logging), and other packages. The ContentTypeManager includes caching to optimize repeated lookups.

Sessions (django.contrib.sessions) manages user session data server-side. The Session model stores session data with a session ID cookie sent to clients. Multiple backends are available: database-backed, cache-backed, and file-based storage. Sessions are entirely cookie-based and do not use URL-based session IDs for security reasons.

Static Files (django.contrib.staticfiles) handles collection and serving of static assets (CSS, JavaScript, images). The FileSystemFinder locates files from STATICFILES_DIRS, while AppDirectoriesFinder discovers static files in app directories. The package provides the collectstatic management command and storage backends for hashing and caching.

Package Dependencies

admin → requires auth, contenttypes
auth → uses contenttypes (for permissions)
contenttypes → no dependencies
sessions → no dependencies
staticfiles → no dependencies

Extension Points

Developers can customize contrib packages through several mechanisms:

  • Admin: Subclass ModelAdmin or AdminSite, override templates, customize forms and filters
  • Auth: Extend AbstractUser, implement custom authentication backends, override permission checks
  • Sessions: Create custom session backends by subclassing SessionBase
  • Static Files: Create custom finders by subclassing BaseFinder, customize storage backends
  • AppConfig: Override AppConfig attributes like ignore_patterns (staticfiles) or default_site (admin)

Installation

Most contrib packages require adding them to INSTALLED_APPS and running migrations:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.staticfiles',
]

Then run python manage.py migrate to create necessary database tables.

Signals & Event Dispatch

Relevant Files
  • django/dispatch/dispatcher.py
  • django/dispatch/init.py
  • django/core/signals.py
  • django/db/models/signals.py
  • django/contrib/auth/signals.py

Django's signal dispatcher is a lightweight publish-subscribe mechanism that decouples application components. Senders notify receivers when specific events occur, enabling clean separation of concerns without tight coupling.

Core Architecture

The Signal class in django/dispatch/dispatcher.py manages the dispatch mechanism. Each signal maintains a list of receivers and uses weak references by default to avoid memory leaks. Signals support both synchronous and asynchronous receivers, executing them appropriately based on context.

Key Components:

  • Receivers: Functions or methods that listen for signals. Must accept **kwargs and be hashable.
  • Senders: Objects that emit signals. Can be a specific instance or None (broadcasts to all).
  • Dispatch UID: Optional unique identifier to prevent duplicate receiver registration.
  • Weak References: Default behavior; strong references available via weak=False.

Connecting & Disconnecting Receivers

from django.dispatch import Signal, receiver
from django.db.models.signals import post_save
from myapp.models import MyModel

# Method 1: Using the @receiver decorator
@receiver(post_save, sender=MyModel)
def my_handler(sender, instance, created, **kwargs):
    if created:
        print(f"New {sender.__name__} created: {instance}")

# Method 2: Manual connection
def another_handler(sender, instance, **kwargs):
    pass

post_save.connect(another_handler, sender=MyModel, dispatch_uid="unique_id")

# Disconnection
post_save.disconnect(another_handler, sender=MyModel, dispatch_uid="unique_id")

Sending Signals

Signals are sent using send() or send_robust(). The send() method propagates exceptions; send_robust() catches them and logs errors.

from django.dispatch import Signal

my_signal = Signal()

# Synchronous send
responses = my_signal.send(sender=self, data="example")
# Returns: [(receiver, response), ...]

# Robust send (catches exceptions)
responses = my_signal.send_robust(sender=self, data="example")

Built-in Signals

Django provides domain-specific signals:

  • Model Signals: pre_init, post_init, pre_save, post_save, pre_delete, post_delete, m2m_changed
  • Core Signals: request_started, request_finished, got_request_exception, setting_changed
  • Auth Signals: user_logged_in, user_login_failed, user_logged_out

Async Support

Signals support async receivers via asend() and asend_robust(). Sync and async receivers are executed separately: sync receivers run first (wrapped in sync_to_async), then async receivers execute concurrently using asyncio.TaskGroup().

@receiver(post_save, sender=MyModel)
async def async_handler(sender, instance, **kwargs):
    await some_async_operation()

ModelSignal & Lazy Senders

ModelSignal extends Signal to support lazy sender references using string notation ("app_label.ModelName"). This enables signal connections before models are fully loaded.

from django.db.models.signals import post_save

# Lazy sender reference
post_save.connect(my_handler, sender="myapp.MyModel", apps=apps)

Performance Considerations

  • Caching: Model signals use use_caching=True to cache receiver lists per sender, reducing lookup overhead.
  • Weak References: Default behavior prevents memory leaks but adds dereferencing overhead.
  • Thread Safety: Uses threading.Lock() to protect receiver list modifications.
  • Dead Receiver Cleanup: Automatically removes garbage-collected receivers via weak reference callbacks.
Loading diagram...