django/django
github.com/django/django ↗ · 4000 files · 32.2 MB · scan capped
Font Awesome 5.0.4 Thanks for downloading Font Awesome!
Overview
Django 6.2.0 alpha is the Django Software Foundation's BSD-licensed Python web framework (Python >= 3.12) for application developers who want an ORM, routing, templates, forms, auth, admin, and migrations without writing that stack themselves. This repository is the framework library, not a deployed site: django-admin startproject emits a project, and runtime configuration comes from DJANGO_SETTINGS_MODULE over django.conf.global_settings. HTTP enters through WSGIHandler or ASGIHandler; management commands enter through execute_from_command_line. Distinctive code in this tree includes a tasks registry whose default backend runs work inline, a MAILERS migration that deprecates EMAIL_* before Django 2028, CSP middleware, and CI that already runs the suite on free-threaded Python 3.14.
System map
The installable product is the django package (setuptools include django*). Process entrypoints are the django-admin console script, python -m django, and the WSGI/ASGI factories. django.setup() is the shared bootstrap: logging, script prefix, then Apps.populate. Settings are a lazy proxy. Persistence is a ConnectionHandler over pluggable database backends, with sqlite3, postgresql, mysql, oracle, and a dummy engine in-tree. There is no application server to deploy from this repo; deployment shape is a generated project plus an external WSGI/ASGI server. Tests and docs are developer-only surfaces driven by tests/runtests.py, tox.ini, and GitHub Actions.
- django/__init__.py sets VERSION to VersionTuple(6, 2, 0, 'alpha', 0) and setup() calls configure_logging, optionally set_script_prefix from FORCE_SCRIPT_NAME, then apps.populate(settings.INSTALLED_APPS).
- pyproject.toml names the project Django, requires Python >= 3.12, depends on asgiref>=3.12.1 and sqlparse>=0.5.0 (tzdata on Windows), and exposes console script django-admin = django.core.management:execute_from_command_line. Optional extras are argon2 (argon2-cffi) and bcrypt.
- python -m django delegates to management.execute_from_command_line() in django/__main__.py. ManagementUtility.execute parses --settings and --pythonpath first, calls django.setup() unless the runserver autoreloader path already did, then fetch_command(subcommand).run_from_argv.
- get_wsgi_application() and get_asgi_application() both call django.setup(set_prefix=False) and return WSGIHandler or ASGIHandler. The handlers are intentionally not the public API.
- LazySettings loads the module named by environment variable DJANGO_SETTINGS_MODULE (ENVIRONMENT_VARIABLE) and raises ImproperlyConfigured if it is unset and settings were not configured manually. User settings overlay django.conf.global_settings.
- Apps.populate is thread-safe and idempotent but not reentrant. It imports AppConfig entries, import_models on each, then calls AppConfig.ready() before setting apps.ready and ready_event.
- django.db.connections is a ConnectionHandler; connection is a ConnectionProxy for the default alias; router is a ConnectionRouter. request_started resets query logs and closes unusable connections; request_finished closes them again.
- Database engines shipped in-tree are django.db.backends.sqlite3, postgresql, mysql, oracle, and dummy. An empty DATABASES ENGINE uses the dummy backend, whose operations raise ImproperlyConfigured. The startproject template sets ENGINE to sqlite3 and NAME to BASE_DIR/db.sqlite3.
- Core management commands are discovered by find_commands via pkgutil.iter_modules on management/commands, mapped by get_commands() (functools.cache) as name -> app. Installed apps override core names because their configs are applied in reverse.
- Built-in command modules include check, dbshell, dumpdata, loaddata, makemigrations, migrate, optimizemigration, runserver, shell, squashmigrations, startapp, startproject, test, and testserver, among others under django/core/management/commands/.
- Default cache backend is django.core.cache.backends.locmem.LocMemCache via CACHES['default']. CacheHandler reads settings.CACHES the same way TaskBackendHandler reads settings.TASKS.
- tox.ini envlist is py3, black, blacken-docs, flake8, docs, isort, lint-docs, and zizmor. The py3 env installs the repo editable, installs tests/requirements/py3.txt, cds to tests, and runs runtests.py. GitHub Actions workflow Tests runs that suite on SQLite for CPython 3.14 (Windows) and free-threaded 3.14t (Ubuntu).
Feature catalog
User-facing surface area is a CLI (django-admin / manage.py), an HTTP stack (URLs, middleware, views, templates, forms), an ORM with migrations, and optional contrib apps. The generated project turns on admin, auth, sessions, messages, and static files, and mounts admin.site.urls at admin/. Batteries that are present in the tree but not in the default project include GIS, Postgres-only fields, flatpages, redirects, sitemaps, and the CSP middleware. A first-party tasks API and a mailers migration sit beside the older email backend.
- Core CLI subcommands implemented as Command classes include check, compilemessages, createcachetable, dbshell, diffsettings, dumpdata, flush, inspectdb, listurls, loaddata, makemessages, makemigrations, migrate, optimizemigration, runserver, sendtestemail, shell, showmigrations, sqlflush, sqlmigrate, sqlsequencereset, squashmigrations, startapp, startproject, test, and testserver.
- runserver starts a development WSGI server (WSGIServer) on 127.0.0.1:8000 by default, with --ipv6, --nothreading, and --noreload. It raises CommandError if DEBUG is False and ALLOWED_HOSTS is empty, and uses autoreload.run_with_reloader unless --noreload is set.
- migrate updates schema via MigrationExecutor. Flags include --fake, --fake-initial, --plan, --run-syncdb, --check (unapplied migrations), and --prune. makemigrations, sqlmigrate, showmigrations, squashmigrations, and optimizemigration are the surrounding schema commands.
- The ORM exposes Model.save/asave/delete and QuerySet.filter, exclude, get, create, iterator, and prefetch. Models are registered through ModelBase and served by a manager API with no code generation, as described in the overview doc.
- django.contrib.admin.sites.AdminSite.register binds a Model to a ModelAdmin (or a dynamic subclass when options are passed). The startproject URLconf mounts path('admin/', admin.site.urls).
- Auth provides ModelBackend (default AUTHENTICATION_BACKENDS), RemoteUserBackend, LoginView/LogoutView/password-reset views in django.contrib.auth.urls, and password hashers selected by PASSWORD_HASHERS. AUTH_USER_MODEL defaults to auth.User.
- Forms: BaseForm.is_valid() is true only when the form is bound and full_clean() produced no errors. full_clean runs _clean_fields (including clean_<field>), _clean_form, and _post_clean.
- The template Engine defaults builtins to defaulttags, defaultfilters, and loader_tags, and when app_dirs is true wraps filesystem and app_directories loaders in the cached loader. Tags and filters register on Library.tags and Library.filters.
- Sessions default to SESSION_ENGINE django.contrib.sessions.backends.db, cookie name sessionid, age two weeks, HttpOnly, SameSite Lax. SessionMiddleware loads the engine from settings and attaches request.session from the cookie.
- Static files use STATICFILES_FINDERS FileSystemFinder and AppDirectoriesFinder. BaseFinder is the extension interface (find/list/check). startproject sets STATIC_URL to 'static/'.
- HTTP middleware shipped under django/middleware includes SecurityMiddleware (HSTS, nosniff, COOP, Referrer-Policy, optional HTTPS redirect), CsrfViewMiddleware, ContentSecurityPolicyMiddleware (SECURE_CSP / SECURE_CSP_REPORT_ONLY), plus cache, clickjacking, common, gzip, http, and locale modules. The project template enables security, sessions, common, csrf, auth, messages, and XFrameOptionsMiddleware, not CSP.
- Tasks: @task / Task.enqueue go through task_backends. The default TASKS backend is django.tasks.backends.immediate.ImmediateBackend, which validates, builds a TaskResult, and runs the callable inside enqueue, emitting task_enqueued, task_started, and task_finished.
Data flow
Configuration flows from the environment into LazySettings, then into the app registry, middleware list, URLConf, and connection handlers. An HTTP request becomes a request object, passes a middleware onion, resolves to a view, and returns an HttpResponse. ORM reads stay as Query objects until evaluation, then SQLCompiler sends SQL and params to a backend cursor. Writes go through Model.save_base and, for schema, through MigrationExecutor. Cross-cutting state (sessions, CSRF, signatures) is keyed by SECRET_KEY or server-side stores.
- WSGIHandler.__call__ sets the script prefix from the WSGI environ, sends request_started, builds a WSGIRequest (method, LimitedStream body capped at CONTENT_LENGTH, GET from QUERY_STRING, cookies from HTTP_COOKIE), then get_response. The iterable returned may be a wsgi.file_wrapper around response.file_to_stream.
- BaseHandler.load_middleware imports each settings.MIDDLEWARE path in reverse, instantiates it with the adapted next handler, and records process_view, process_template_response, and process_exception hooks. MiddlewareNotUsed skips an entry. get_response sets the thread URLConf to ROOT_URLCONF, runs the chain, and logs status >= 400.
- resolve_request uses request.urlconf if set, otherwise get_resolver(), then URLResolver.resolve(request.path_info). resolve walks url_patterns, merges kwargs, and returns a ResolverMatch. request_finished is connected to reset_urlconf.
- If the view returns an object with a callable render(), template-response middleware runs and then response.render() is called. A None or unawaited coroutine from a view raises ValueError. Async views on the sync path are wrapped with async_to_sync.
- QuerySet.filter clones via _chain and adds a Q object in _filter_or_exclude_inplace; it raises TypeError if the query is already sliced. Evaluation is deferred until _fetch_all, which lists self._iterable_class(self) and then runs prefetch_related if needed.
- SQLCompiler.execute_sql compiles with as_sql(), opens connection.cursor() or chunked_cursor(), and calls cursor.execute(sql, params). Result shape depends on MULTI, SINGLE, ROW_COUNT, or CURSOR. EmptyResultSet short-circuits.
- Model.save picks a database with router.db_for_write, optionally narrows update_fields for deferred instances, then save_base sends pre_save, writes inside transaction.atomic (if the model has parents) or mark_for_rollback_on_error, stores _state.db, clears _state.adding, and sends post_save with created=(not updated).
- MigrationExecutor.migrate ensures the django_migrations table unless the plan is empty, builds a plan, rejects mixed forward and backward plans with InvalidMigrationPlan, and applies forward migrations in full_plan order via apply_migration.
- CSRF: CsrfViewMiddleware reads the secret from the session (CSRF_USE_SESSIONS, key requires SessionMiddleware first) or from cookie CSRF_COOKIE_NAME (default csrftoken). Unsafe methods must present csrfmiddlewaretoken in POST or the header named by CSRF_HEADER_NAME (default HTTP_X_CSRFTOKEN). Failures go to CSRF_FAILURE_VIEW.
- HttpRequest.get_host validates the raw host against ALLOWED_HOSTS via validate_host. If DEBUG is true and ALLOWED_HOSTS is empty, the allow-list becomes .localhost, 127.0.0.1, and [::1]. Otherwise it raises DisallowedHost. is_secure consults SECURE_PROXY_SSL_HEADER before the scheme.
- Signed cookies: HttpRequest.get_signed_cookie calls signing._unsign_cookie and re-raises BadSignature unless a default is supplied. SIGNING_BACKEND defaults to django.core.signing.TimestampSigner. The signing module documents HMAC/SHA-256 over URL-safe base64 JSON using the project secret.
- Upload bounds in global settings: DATA_UPLOAD_MAX_MEMORY_SIZE and FILE_UPLOAD_MAX_MEMORY_SIZE are 2621440 bytes, DATA_UPLOAD_MAX_NUMBER_FIELDS is 1000, and DATA_UPLOAD_MAX_NUMBER_FILES is 100. WSGIRequest wraps wsgi.input in LimitedStream so reads cannot pass CONTENT_LENGTH.
Behavior traces
Three flows dominate day-to-day work: process startup for django-admin, the per-request path from handler to view, and the persistence path from QuerySet or Model.save through SQL and migrations. Auth and CSRF are the security-critical variants of the request path. Names below are the functions actually called, in order.
- CLI startup order: execute_from_command_line -> ManagementUtility.execute -> CommandParser known-args for --settings/--pythonpath -> handle_default_options -> django.setup (configure_logging, set_script_prefix, apps.populate) -> autocomplete if DJANGO_AUTO_COMPLETE is set -> fetch_command -> load_command_class -> BaseCommand.run_from_argv -> execute (system checks unless skipped) -> Command.handle. No subcommand prints help.
- runserver special case: if the subcommand is runserver and --noreload is absent, ManagementUtility calls autoreload.check_errors(django.setup) before the command class is loaded, and on failure pretends the app registry is ready so the reloader child can show the exception. Command.handle then inner_run via run_with_reloader, serving get_internal_wsgi_application().
- Sync HTTP order: WSGIHandler.__call__ -> signals.request_started (reset_queries, close_old_connections) -> WSGIRequest -> BaseHandler.get_response -> set_urlconf(ROOT_URLCONF) -> middleware chain -> _get_response -> resolve_request -> URLResolver.resolve -> make_view_atomic -> view(request, *args, **kwargs) -> optional process_exception -> optional TemplateResponse.render -> start_response.
- ASGI differs at the edges: ASGIHandler serves ASGIRequest built from scope (path, method, query_string, root_path) and uses get_response_async so async views are awaited and sync views run via sync_to_async(thread_sensitive=True). body_receive_timeout is 60 seconds.
- Class-based view order: URL resolver calls the callable returned by View.as_view -> view() constructs the class, calls setup (stores request/args/kwargs, aliases head to get), then dispatch, which lowercases request.method and invokes that handler or http_method_not_allowed.
- Read query order: QuerySet.filter -> _filter_or_exclude -> _chain/_clone -> _filter_or_exclude_inplace -> Query.add_q(Q). Later iteration calls _fetch_all -> ModelIterable -> SQL compiler as_sql -> SQLCompiler.execute_sql -> cursor.execute. prefetch_related runs only after the primary result list exists.
- Write order: Model.save -> _prepare_related_fields_for_save -> router.db_for_write -> save_base -> pre_save.send -> _save_parents (when not raw) -> _save_table -> _do_insert or _do_update -> post_save.send. asave is sync_to_async(self.save). Empty update_fields returns before signals.
- migrate command order: Command.handle reads --database (default alias), builds a MigrationExecutor for that connection, plans targets, and calls executor.migrate. Forward application renders project state (state.apps) once, then apply_migration for each selected node. --fake records without running SQL.
- Login order: authenticate walks AUTHENTICATION_BACKENDS, calls backend.authenticate, stops on PermissionDenied, and on total failure sends user_login_failed. ModelBackend.authenticate loads the user with get_by_natural_key and check_password_with_timing_attack_mitigation, then user_can_authenticate (is_active). login() stores the user pk and session auth hash, flushing the session if it belonged to someone else, otherwise cycle_key.
- CSRF failure order on an unsafe request: process_view -> _get_secret (cookie or session) -> _check_token compares the POST or header token -> RejectRequest -> _reject -> CSRF_FAILURE_VIEW (default django.views.csrf.csrf_failure) -> log_response Forbidden. HTTPS requests also pass _origin_verified and _check_referer.
- Password check order: check_password -> verify_password -> identify_hasher (algorithm is the prefix before $, with legacy unsalted md5/sha1 shapes) -> hasher.verify. If the preferred hasher differs or must_update, and a setter is passed, the password is re-encoded. Missing users still run make_password once to reduce timing differences.
- System-check order inside a command: BaseCommand.execute, when requires_system_checks and not skip_checks, calls self.check, then check_migrations if required, then handle. call_command forces skip_checks=True unless the caller passed that option. Deployment-tagged checks such as check_secret_key are omitted unless include_deployment_checks is set.
Testing signals
Django tests Django with its own test runner. The suite lives in tests/ and is launched by tests/runtests.py, not by a third-party discovery command. Default CI is SQLite on CPython 3.14 plus a free-threading job; JavaScript admin tests and scripts/ unit tests are separate jobs. Lint is flake8, isort, black, and zizmor. Postgres, MySQL, Oracle, and PostGIS need extra settings and are not what tox runs by default. Deprecation and resource warnings are treated as errors, so a behavior change that trips RemovedInNextVersionWarning fails the suite.
- tests/runtests.py imports django.test.TestCase, TransactionTestCase, and get_runner (TEST_RUNNER default django.test.runner.DiscoverRunner). It filters RemovedInNextVersionWarning, RemovedAfterNextVersionWarning, ResourceWarning, and RuntimeWarning as errors, and raises GC thresholds on CPython.
- Discovery scans tests/ for packages containing __init__.py. SUBDIRS_TO_SKIP always skips import_error_package, playwright_tests, and test_runner_apps. gis_tests is skipped unless GIS is enabled, and gis_tests/data is always skipped. The documented invocation is cd tests && ./runtests.py after pip install -e .. and tests/requirements/py3.txt.
- The runner always installs contenttypes, auth, sites, sessions, messages, django.contrib.admin.apps.SimpleAdminConfig, and staticfiles, and always enables SessionMiddleware, CommonMiddleware, CsrfViewMiddleware, AuthenticationMiddleware, and MessageMiddleware. flatpages and redirects are added only for their test labels.
- tox default environments are py3, black, blacken-docs, flake8, docs, isort, lint-docs, and zizmor. Database factors such as postgres, mysql, and oracle append extra requirements but still need a settings module the suite does not vendor, for example tox -e py312-postgres -- --settings=my_postgres_settings. Free-threaded envs py314t and py313t exist.
- .github/workflows/tests.yml on pull_request and push to main (ignoring docs/**) runs python -Wall tests/runtests.py -v2 for Windows/SQLite/Python 3.14 and Ubuntu/SQLite/Python 3.14t, npm test for admin JavaScript, and python -m unittest discover -v -s scripts/.
- JavaScript coverage is QUnit via Grunt: package.json scripts.test is grunt test --verbose, devDependencies include qunit, grunt-contrib-qunit, and @biomejs/biome. Test files live under js_tests/admin (actions, DateTimeShortcuts, inlines, SelectBox, URLify) and js_tests/gis/mapwidget.test.js.
- Linters workflow runs flake8, isort --check --diff django tests scripts, black (psf/black@stable), and zizmor. pyproject.toml configures black target-version py312 and isort profile black with known_first_party django.
- Playwright browser tests are label-gated: .github/workflows/playwright.yml runs only when the pull request has the playwright label, then installs apt packages and Playwright browsers. runtests.py imports PlaywrightTestCase but does not discover tests/playwright_tests during the normal scan.
- Topic packages under tests/ include auth_tests, csrf_tests, handlers, migrations-related packages, admin_views, forms_tests, gis_tests, composite_pk, and file_uploads. Policy in the contributing doc is that the suite must pass at all times and that new tests use Django's own test infrastructure.
- GIS-related tests depend on native libraries. tox passenv forwards GDAL_LIBRARY_PATH, GEOS_LIBRARY_PATH, and SPATIALITE_LIBRARY_PATH. The default Tests workflow jobs read above do not install those libraries, so a green SQLite run is not evidence that django.contrib.gis was exercised.
- django.test.client exposes Client, AsyncClient, RequestFactory, and AsyncRequestFactory. They build WSGIRequest or ASGIRequest and drive BaseHandler, and FakePayload refuses seeks so views cannot read the body differently than on a real socket.
- scripts/ has its own unittest discovery (CI job scripts-tests), including scripts/pr_quality tests. That job does not install the Django test requirements file used by runtests.py.
Risk map
The sharp edges are secret handling, host and CSRF checks, password-hasher compatibility, shell-outs, and a few APIs that look asynchronous or durable but are not. Deployment checks for SECRET_KEY do not run on ordinary manage.py check. The generated project is explicitly unsuitable for production (DEBUG True). Schema and request code have hard incompatibilities: mixed migration directions, ATOMIC_REQUESTS with async views, and admin registration of composite primary keys.
- startproject writes SECRET_KEY into settings and sets DEBUG = True with ALLOWED_HOSTS = []. The template comments say both are unsuitable for production. check_secret_key (security.W009) only runs as a deploy=True check and flags length < 50, fewer than 5 unique characters, or the django-insecure- prefix.
- HttpRequest.get_host allows any *.localhost, 127.0.0.1, and [::1] when DEBUG is true and ALLOWED_HOSTS is empty. SECURE_PROXY_SSL_HEADER is None by default and global_settings warns that setting it without a trusted proxy allows scheme spoofing.
- CSRF_COOKIE_HTTPONLY defaults to False so client script can read csrftoken. CSRF_TRUSTED_ORIGINS defaults to empty. A missing SessionMiddleware with CSRF_USE_SESSIONS raises ImproperlyConfigured from _get_secret.
- MD5PasswordHasher (algorithm md5) is still implemented and documented as not recommended, but it is not in the default PASSWORD_HASHERS list. identify_hasher still accepts 32-character unsalted MD5 and sha1$$ legacy hashes and will call get_hasher for those algorithms if they remain configured.
- get_git_changeset runs a fixed git log command via subprocess.run(..., shell=True) with cwd two directories above django/utils/version.py, and uses stdout as a version timestamp. The command string is not user input, but shell=True is still a process boundary.
- dbshell reaches the database client through BaseDatabaseClient.runshell, which merges the backend env over os.environ and calls subprocess.run(args, env=env, check=True) without shell=True. The executable name is backend-defined (psql and similar).
- SafeExceptionReporterFilter.hidden_settings redacts keys matching API, AUTH, TOKEN, KEY, SECRET, PASS, SIGNATURE, and HTTP_COOKIE, plus the session cookie name, before the debug exception reporter shows settings. DEFAULT_EXCEPTION_REPORTER_FILTER points at this class. Debug pages are still a risk if DEBUG is left on.
- ImmediateBackend executes task functions in the calling process during enqueue, stores tracebacks on failure, and does not persist results beyond the returned TaskResult. Treating settings.TASKS['default'] as a durable queue will drop work when the process exits.
- Email has two configuration paths during the Django 6.x cycle. EMAIL_BACKEND and related EMAIL_* settings are marked RemovedInDjango2028Warning, get_connection() warns, and defining MAILERS together with any deprecated email setting raises ImproperlyConfigured.
- make_view_atomic wraps a view in transaction.atomic for every alias with ATOMIC_REQUESTS unless the view lists that alias in _non_atomic_requests. If the view is a coroutine function it raises RuntimeError instead of wrapping.
- AdminSite.register raises ImproperlyConfigured for abstract models and for models with _meta.is_composite_pk, and AlreadyRegistered if the model is already in the registry. Swapped models are silently not registered.
- Apps.populate raises RuntimeError if called reentrantly while loading, which happens if AppConfig.ready() or a model import triggers setup again. get_commands is functools.cache, so tests that mutate INSTALLED_APPS without clearing that cache see a stale command map.
Extension points
Django is built as registries plus import strings. New behavior is expected to plug in through INSTALLED_APPS, MIDDLEWARE, management command modules, database and cache and task backends, URL converters, lookups, template libraries, checks, signals, admin classes, and serializers. Most of these are configured from settings rather than a single plugin entry file. Contrib apps are ordinary apps that happen to ship in the django package.
- Application plugins are INSTALLED_APPS entries. AppConfig.create loads each entry; ready() runs after models import. Duplicate labels or duplicate app names raise ImproperlyConfigured. startapp scaffolds from django/conf/app_template/*.py-tpl.
- HTTP plugins are dotted paths in settings.MIDDLEWARE. BaseHandler.load_middleware import_string's each one and requires sync_capable or async_capable. MiddlewareNotUsed drops an entry at runtime.
- CLI plugins are modules named management/commands/<name>.py inside an installed app (or django.core). find_commands lists them; load_command_class imports module.Command. Later apps override earlier command names.
- Auth plugins are AUTHENTICATION_BACKENDS (default ModelBackend) and PASSWORD_HASHERS. get_hasher('default') returns the first hasher. A custom hasher subclasses BasePasswordHasher and must set algorithm, verify, encode, and safe_summary.
- Database plugins are DATABASES[alias]['ENGINE'] pointing at a backend package with DatabaseWrapper, plus optional DATABASE_ROUTERS. The dummy backend is the empty-ENGINE fallback. Custom lookups register via RegisterLookupMixin.register_lookup, which writes class_lookups or instance_lookups.
- URL plugins: path, re_path, and include build URLPattern and URLResolver trees. register_converter adds path converters; built-ins include IntConverter, StringConverter, UUIDConverter, SlugConverter, and PathConverter.
- Template plugins: a templatetags module exposes a Library (conventionally register). Engine accepts libraries and extra builtins. default_builtins are defaulttags, defaultfilters, and loader_tags.
- System checks plug in through CheckRegistry.register, usable as a decorator with tags. deploy=True puts the check in deployment_checks, which run_checks includes only when asked. Tags include admin, models, security, database, and urls.
- Signals: django.dispatch.Signal is the shared bus. ORM code sends pre_save and post_save. Request lifecycle uses request_started and request_finished. Task backends send task_enqueued, task_started, and task_finished. Receivers can be sync or async.
- Admin plugins: subclass ModelAdmin and call AdminSite.register(model, admin_class) or admin.site.register. Keyword options to register() build a dynamic subclass. Autodiscover imports each app's admin module.
- Cache, task, and mailer backends are alias maps of BACKEND import strings: CACHES via CacheHandler, TASKS via TaskBackendHandler.create_connection, and MAILERS via the mailers handler. Session stores swap by setting SESSION_ENGINE to a module that defines SessionStore.
- Serializers plug in through register_serializer(format, dotted_module). Built-ins cover xml, python, json, yaml, and jsonl. dumpdata/loaddata consume that registry.
Contributor handoff
Edit the django/ package as a library with a stable import surface, and prove changes with a narrow runtests.py label. Read the handler, settings, and the subsystem you touch before writing code. Black, isort, and flake8 are enforced. Deprecation warnings are test failures. Do not treat this checkout as an application: there is no project settings module until startproject creates one. Avoid full-suite runs, native GIS, and alternate databases unless the task needs them.
- Read first: django/__init__.py (version and setup), django/conf/__init__.py plus global_settings.py, django/core/handlers/base.py, django/core/management/__init__.py, and the subsystem file (ORM query.py/base.py, urls/resolvers.py, or the contrib app). Design intent is loose coupling: templates do not know about requests, the database layer does not know about display.
- Safe test command, from a venv with pip install -e . and tests/requirements/py3.txt: cd tests && ./runtests.py <label> -v2. Labels are package names such as handlers, csrf_tests, or auth_tests. tox -e py3 -- <label> is the same runner. Do not start with the full suite.
- Formatting: black target py312 (force-excludes tests/test_runner_apps/tagged/tests_syntax_error.py) and isort profile black, known_first_party django, checked on django, tests, and scripts. flake8 is the lint gate in CI.
- runtests.py makes RemovedInNextVersionWarning, RemovedAfterNextVersionWarning, ResourceWarning, and RuntimeWarning errors. Code that emits those warnings fails CI even if assertions pass. EMAIL_* and get_connection() already warn with RemovedInDjango2028Warning.
- Settings trap: any import-time access to django.conf.settings before DJANGO_SETTINGS_MODULE or settings.configure() raises ImproperlyConfigured. Model import before apps.populate raises AppRegistryNotReady. Tests rely on runtests.py to configure settings; ad-hoc scripts must do it themselves.
- call_command() sets skip_checks=True by default, so it will not reproduce a failing system check that run_from_argv would run. ManagementUtility fetches commands only after setup, except the runserver autoreload bootstrap.
- get_commands is functools.cache. Adding a command module or changing INSTALLED_APPS in-process requires clearing that cache or the new command stays invisible. Command instances live in app packages as class Command(BaseCommand).
- Project and app scaffolds are .py-tpl files under django/conf/project_template and django/conf/app_template, not .py modules. Editing a generated-looking settings.py that is not in the tree will not change startproject.
- Do not hand-edit compiled .mo catalogs under django/conf/locale or contrib/*/locale. Translation source is the .po files; makemessages and compilemessages are the commands. isort/black CI does not cover those catalogs the way it covers Python. (inferred)
- Async trap: a coroutine view cannot be combined with ATOMIC_REQUESTS. Admin trap: composite primary keys and abstract models cannot be registered. Migration trap: a plan that both applies and unapplies in one executor.migrate call raises InvalidMigrationPlan.
- Security-sensitive edits belong with the matching tests: csrf_tests for CsrfViewMiddleware, auth_tests for hashers and backends, check_framework or security checks for W009. Deployment checks do not run unless include_deployment_checks is requested, so a unit test must opt in.
- GIS and non-SQLite backends are optional. Changing django/contrib/gis or django/db/backends/postgresql|mysql|oracle is not validated by the default GitHub Actions SQLite job. tox only adds those drivers when the env factor is selected, and you must pass --settings.
Languages
| Language | Files | Share of source |
|---|---|---|
| Python | 2932 | 96% |
| HTML | 373 | docs/config |
| JavaScript | 111 | 4% |
| JSON | 55 | docs/config |
| CSS | 48 | docs/config |
| YAML | 26 | docs/config |
| Markdown | 9 | docs/config |
| Shell | 2 | 0% |
Start reading here
Probable source entrypoint: django/__init__.py — inferred from the directory tree and manifest, not the upstream docs.
Source roots
django/ (1610 files)
Source layout — django/
| Path | Files |
|---|---|
django/apps/ | 3 |
django/conf/ | 221 |
django/__init__.py | 1 |
django/__main__.py | 1 |
Repository structure
| Top-level path | Files |
|---|---|
django/ | 1610 |
tests/ | 1609 |
docs/ | 704 |
.github/ | 29 |
scripts/ | 13 |
js_tests/ | 12 |
extras/ | 2 |
.tx/ | 1 |
Docs found: docs/_theme/djangodocs/static/fontawesome/README.md
Package
package.json — Django, 5 declared dependencies.
@biomejs/biomegruntgrunt-cligrunt-contrib-qunitqunit
CI & config entrypoints
.github/workflows/benchmark.yml— GitHub Actions workflow.github/workflows/check-migrations.yml— GitHub Actions workflow.github/workflows/check_commit_messages.yml— GitHub Actions workflow.github/workflows/check_pr_quality.yml— GitHub Actions workflow.github/workflows/coverage_comment.yml— GitHub Actions workflow.github/workflows/coverage_tests.yml— GitHub Actions workflow.github/workflows/data/conda/geolibs-pg17-freethreading.yml— GitHub Actions workflow.github/workflows/data/conda/geolibs-pg17-gil.yml— GitHub Actions workflow.github/workflows/data/conda/geolibs-pg18-freethreading.yml— GitHub Actions workflow.github/workflows/data/conda/geolibs-pg18-gil.yml— GitHub Actions workflow
Structural health signals
Average score 6.1/10 across 96 analyzed source files; 80 hotspots surfaced.
django/db/backends/base/schema.py— 1177 lines, score 4.7 (Large file, Deep nesting)django/test/client.py— 1489 lines, score 4.7 (Large file, Deep nesting)django/db/models/fields/related_descriptors.py— 1216 lines, score 4.7 (Large file, Deep nesting)
These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.
Recent history
dd6f6b1531982026-09-20 — Corrected output of Prefetch.to_attr example.85647bccc1992026-09-04 — Fixed #37321 -- Documented BaseSpatialField.srid=-1 behavior.446d9cf602a52026-09-13 — Fixed #37114 -- Dropped support for PostgreSQL 15 and PostGIS 3.2.82f34e2f72902026-09-19 — Refs #36947 -- Added supports_comments skip to test_alter_generated_field_base_field_comment.935edaa91b752026-09-19 — Fixed #37357 -- Handled out-of-range year in admin date_hierarchy.