Django Knowledge Patch
Use this patch when implementing, reviewing, testing, or upgrading Django applications and
extensions. Start with the compatibility checks, then open only the topic references needed for
the work.
Reference index
| Reference |
Topics |
| upgrading.md |
Runtime and database floors, removals, deprecations, release status, upgrade boundaries |
| orm-and-databases.md |
Composite keys, expressions, queries, migrations, database options, backend APIs |
| http-security-auth.md |
CSP, content negotiation, redirects, URL handling, authentication, sessions, passwords, DRF |
| tasks.md |
Task declaration, backends, enqueueing, serialization, transactions, context, and results |
| templates-forms-admin.md |
Template partials and tags, forms, accessibility, media, and admin behavior |
| email-and-feeds.md |
Mail backends, modern email objects, attachments, calling conventions, addresses, and feeds |
| gis.md |
Geometry APIs, spatial operations, GeoIP2, widgets, validation, and backend support |
| tooling-testing-serialization.md |
Shell imports, commands, testing, serializers, scaffolding, static files, and protocols |
Check breaking changes first
Before changing application code or dependencies:
- Read upgrading.md for supported runtimes and database floors.
- Search for removed APIs before treating an import, signature, or configuration failure as a
local bug.
- Check deprecation boundaries against the application's next intended upgrade.
- For custom database backends, fields, lookups, mail classes, middleware, form renderers, or
GIS widgets, read the matching extension notes before changing a compatibility shim.
High-risk compatibility changes include:
- Storage configuration must use
STORAGES and storage aliases; legacy storage settings and
get_storage_class() are gone.
- Removed ORM extension hooks include joining-column fallbacks, singular prefetch-queryset hooks,
and field-cache naming hooks.
- Custom lookup and expression SQL methods must return parameter tuples, and custom
Field.pre_save() implementations must be idempotent.
- Core mail helpers require optional parameters by keyword on the path to the next removal
boundary; modern mail objects replace the legacy safe-MIME APIs.
ModelAdmin.lookup_allowed() overrides need request; format_html() needs arguments; and
BaseConstraint no longer accepts positional arguments.
- URL fields now assume HTTPS, while template
urlize behavior has a separate transition.
Work with composite primary keys
Declare a virtual primary key whose component order defines tuple assignment and lookup:
class OrderLineItem(models.Model):
pk = models.CompositePrimaryKey("product_id", "order_id")
product = models.ForeignKey(Product,
order = models.ForeignKey(Order,
item = OrderLineItem.objects.get(pk=(1, "A755H"))
Account for these boundaries:
- Migrations cannot add, remove, or convert a composite primary key or its component fields.
Change the database schema separately and synchronize migration state explicitly.
- Foreign keys, generic relations, and the admin do not support composite-key models.
- Reusable code should inspect
_meta.pk_fields; component fields do not individually report
primary_key=True.
- The virtual
pk is omitted from ModelForms, and validation exclusion behavior differs
between field cleaning and uniqueness validation.
- Most single-expression functions reject composite expressions;
Count("pk") is supported.
- Raw queries and exact subqueries can work with composite keys in current APIs.
Read orm-and-databases.md before writing migrations,
relations, expressions, forms, reusable introspection, or custom database code around them.
Queue work with the Tasks API
Declare a task and enqueue it instead of invoking the decorated object:
from django.tasks import task
@task(priority=2, queue_name="emails")
def email_users(user_ids):
...
result = email_users.enqueue([1, 2])
ImmediateBackend executes synchronously; DummyBackend only records enqueue operations.
- Production execution requires a third-party backend and worker.
- Pass values that survive a JSON round trip, such as identifiers rather than model instances,
datetimes, or tuples.
- Use
transaction.on_commit() when the work depends on newly committed rows.
- Use
aenqueue() in async code, and verify backend support for priorities, delayed execution,
and result retrieval.
Read tasks.md before configuring aliases, overriding options, using task
context, or consuming a TaskResult.
Configure Content Security Policy deliberately
Install ContentSecurityPolicyMiddleware and configure SECURE_CSP,
SECURE_CSP_REPORT_ONLY, or both. Use django.utils.csp.CSP constants for quoted source values.
from django.utils.csp import CSP
SECURE_CSP_REPORT_ONLY = {
"script-src": [CSP.SELF, CSP.NONCE, CSP.STRICT_DYNAMIC],
"report-uri": "/csp-reports/",
}
- Report-only configuration needs a reporting directive and an application-provided receiver.
- Add the CSP context processor before rendering
nonce="{{ csp_nonce }}".
- Do not full-page-cache responses containing per-request nonces.
- View decorators replace the global mapping rather than merging it; an empty mapping disables
that header for the view.
Read http-security-auth.md for middleware, password,
authentication, session, redirect, negotiation, URL, and cookie behavior.
Render template fragments
Define and render a named fragment in the template, or append #<partial-name> to a template
name to render only that fragment from a view:
{% partialdef filter_controls inline %}
<form>{{ filter_form }}</form>
{% endpartialdef %}
{% partial filter_controls %}
Use simple_block_tag() when a paired tag only needs its already-rendered block content. Open
templates-forms-admin.md for custom BoundField
selection, error accessibility, script media, parser metadata, and admin extension changes.
Use current HTTP helpers
- Call
request.get_preferred_type() with producible media types in server-preference order and
handle None when none are acceptable.
- Pass
query= and fragment= to reverse() or reverse_lazy().
- Set
preserve_request=True on redirects that must preserve the method and body.
- Pass
query_params= to request factories and test clients for any HTTP method.
- Configure DRF authentication policy explicitly;
LoginRequiredMiddleware intentionally does
not enforce login on DRF API views.
Use current ORM behavior safely
values() and values_list() keep the requested projection order.
- The cross-backend
StringAgg delimiter is an expression; wrap a literal with Value().
Aggregate.order_by is available only on aggregate classes opting in with allow_order_by.
AnyValue supplies an arbitrary non-null representative where backend grouping rules need it.
- Database-computed values after
save() are returned immediately on some backends and become
deferred until access on MySQL and MariaDB.
- Catch the model-specific
Model.NotUpdated when a forced update affects no rows.
- Use
AsyncPaginator and AsyncPage in async code.
- Treat
fetch_mode() and database-level on_delete actions as explicit query/schema choices,
not drop-in changes to existing behavior.
Open orm-and-databases.md for detailed backend capabilities,
migration behavior, patch-level fixes, and extension contracts.
Modernize email integrations
Prefer email.message.MIMEPart for structured and inline attachments. Expect
EmailMessage.message() to return the standard-library message object with the modern policy.
Treat attachments and alternatives as named tuples where exposed, and add alternatives only with
attach_alternative().
Open email-and-feeds.md before maintaining custom mail classes,
multiple backend aliases, legacy MIME attachments, header validation, administrator addresses, or
feed stylesheets.
Implementation workflow
- Identify the affected topic and open its reference file.
- Check both the current behavior and the next removal boundary.
- Distinguish core support from backend-specific and opt-in capabilities.
- Preserve async behavior when wrapping views, middleware, authentication, pagination, or tasks.
- Run Django system checks and focused tests after changing extension points.
- Test migrations against both model state and database state for state-only operations.
- Test generated SQL and parameter types for custom ORM components.
- Verify security headers, nonce uniqueness, redirects, content negotiation, and URL validation
at the HTTP boundary.
1---2name: django-knowledge-patch3description: Django4license: MIT5---678# Django Knowledge Patch910Use this patch when implementing, reviewing, testing, or upgrading Django applications and11extensions. Start with the compatibility checks, then open only the topic references needed for12the work.1314## Reference index1516| Reference | Topics |17| --- | --- |18| [upgrading.md](references/upgrading.md) | Runtime and database floors, removals, deprecations, release status, upgrade boundaries |19| [orm-and-databases.md](references/orm-and-databases.md) | Composite keys, expressions, queries, migrations, database options, backend APIs |20| [http-security-auth.md](references/http-security-auth.md) | CSP, content negotiation, redirects, URL handling, authentication, sessions, passwords, DRF |21| [tasks.md](references/tasks.md) | Task declaration, backends, enqueueing, serialization, transactions, context, and results |22| [templates-forms-admin.md](references/templates-forms-admin.md) | Template partials and tags, forms, accessibility, media, and admin behavior |23| [email-and-feeds.md](references/email-and-feeds.md) | Mail backends, modern email objects, attachments, calling conventions, addresses, and feeds |24| [gis.md](references/gis.md) | Geometry APIs, spatial operations, GeoIP2, widgets, validation, and backend support |25| [tooling-testing-serialization.md](references/tooling-testing-serialization.md) | Shell imports, commands, testing, serializers, scaffolding, static files, and protocols |2627## Check breaking changes first2829Before changing application code or dependencies:30311. Read [upgrading.md](references/upgrading.md) for supported runtimes and database floors.322. Search for removed APIs before treating an import, signature, or configuration failure as a33 local bug.343. Check deprecation boundaries against the application's next intended upgrade.354. For custom database backends, fields, lookups, mail classes, middleware, form renderers, or36 GIS widgets, read the matching extension notes before changing a compatibility shim.3738High-risk compatibility changes include:3940- Storage configuration must use `STORAGES` and storage aliases; legacy storage settings and41 `get_storage_class()` are gone.42- Removed ORM extension hooks include joining-column fallbacks, singular prefetch-queryset hooks,43 and field-cache naming hooks.44- Custom lookup and expression SQL methods must return parameter tuples, and custom45 `Field.pre_save()` implementations must be idempotent.46- Core mail helpers require optional parameters by keyword on the path to the next removal47 boundary; modern mail objects replace the legacy safe-MIME APIs.48- `ModelAdmin.lookup_allowed()` overrides need `request`; `format_html()` needs arguments; and49 `BaseConstraint` no longer accepts positional arguments.50- URL fields now assume HTTPS, while template `urlize` behavior has a separate transition.5152## Work with composite primary keys5354Declare a virtual primary key whose component order defines tuple assignment and lookup:5556```python57class OrderLineItem(models.Model):58 pk = models.CompositePrimaryKey("product_id", "order_id")59 product = models.ForeignKey(Product, on_delete=models.CASCADE)60 order = models.ForeignKey(Order, on_delete=models.CASCADE)6162item = OrderLineItem.objects.get(pk=(1, "A755H"))63```6465Account for these boundaries:6667- Migrations cannot add, remove, or convert a composite primary key or its component fields.68 Change the database schema separately and synchronize migration state explicitly.69- Foreign keys, generic relations, and the admin do not support composite-key models.70- Reusable code should inspect `_meta.pk_fields`; component fields do not individually report71 `primary_key=True`.72- The virtual `pk` is omitted from `ModelForm`s, and validation exclusion behavior differs73 between field cleaning and uniqueness validation.74- Most single-expression functions reject composite expressions; `Count("pk")` is supported.75- Raw queries and exact subqueries can work with composite keys in current APIs.7677Read [orm-and-databases.md](references/orm-and-databases.md) before writing migrations,78relations, expressions, forms, reusable introspection, or custom database code around them.7980## Queue work with the Tasks API8182Declare a task and enqueue it instead of invoking the decorated object:8384```python85from django.tasks import task8687@task(priority=2, queue_name="emails")88def email_users(user_ids):89 ...9091result = email_users.enqueue([1, 2])92```9394- `ImmediateBackend` executes synchronously; `DummyBackend` only records enqueue operations.95- Production execution requires a third-party backend and worker.96- Pass values that survive a JSON round trip, such as identifiers rather than model instances,97 datetimes, or tuples.98- Use `transaction.on_commit()` when the work depends on newly committed rows.99- Use `aenqueue()` in async code, and verify backend support for priorities, delayed execution,100 and result retrieval.101102Read [tasks.md](references/tasks.md) before configuring aliases, overriding options, using task103context, or consuming a `TaskResult`.104105## Configure Content Security Policy deliberately106107Install `ContentSecurityPolicyMiddleware` and configure `SECURE_CSP`,108`SECURE_CSP_REPORT_ONLY`, or both. Use `django.utils.csp.CSP` constants for quoted source values.109110```python111from django.utils.csp import CSP112113SECURE_CSP_REPORT_ONLY = {114 "script-src": [CSP.SELF, CSP.NONCE, CSP.STRICT_DYNAMIC],115 "report-uri": "/csp-reports/",116}117```118119- Report-only configuration needs a reporting directive and an application-provided receiver.120- Add the CSP context processor before rendering `nonce="{{ csp_nonce }}"`.121- Do not full-page-cache responses containing per-request nonces.122- View decorators replace the global mapping rather than merging it; an empty mapping disables123 that header for the view.124125Read [http-security-auth.md](references/http-security-auth.md) for middleware, password,126authentication, session, redirect, negotiation, URL, and cookie behavior.127128## Render template fragments129130Define and render a named fragment in the template, or append `#<partial-name>` to a template131name to render only that fragment from a view:132133```django134{% partialdef filter_controls inline %}135 <form>{{ filter_form }}</form>136{% endpartialdef %}137{% partial filter_controls %}138```139140Use `simple_block_tag()` when a paired tag only needs its already-rendered block content. Open141[templates-forms-admin.md](references/templates-forms-admin.md) for custom `BoundField`142selection, error accessibility, script media, parser metadata, and admin extension changes.143144## Use current HTTP helpers145146- Call `request.get_preferred_type()` with producible media types in server-preference order and147 handle `None` when none are acceptable.148- Pass `query=` and `fragment=` to `reverse()` or `reverse_lazy()`.149- Set `preserve_request=True` on redirects that must preserve the method and body.150- Pass `query_params=` to request factories and test clients for any HTTP method.151- Configure DRF authentication policy explicitly; `LoginRequiredMiddleware` intentionally does152 not enforce login on DRF API views.153154## Use current ORM behavior safely155156- `values()` and `values_list()` keep the requested projection order.157- The cross-backend `StringAgg` delimiter is an expression; wrap a literal with `Value()`.158- `Aggregate.order_by` is available only on aggregate classes opting in with `allow_order_by`.159- `AnyValue` supplies an arbitrary non-null representative where backend grouping rules need it.160- Database-computed values after `save()` are returned immediately on some backends and become161 deferred until access on MySQL and MariaDB.162- Catch the model-specific `Model.NotUpdated` when a forced update affects no rows.163- Use `AsyncPaginator` and `AsyncPage` in async code.164- Treat `fetch_mode()` and database-level `on_delete` actions as explicit query/schema choices,165 not drop-in changes to existing behavior.166167Open [orm-and-databases.md](references/orm-and-databases.md) for detailed backend capabilities,168migration behavior, patch-level fixes, and extension contracts.169170## Modernize email integrations171172Prefer `email.message.MIMEPart` for structured and inline attachments. Expect173`EmailMessage.message()` to return the standard-library message object with the modern policy.174Treat attachments and alternatives as named tuples where exposed, and add alternatives only with175`attach_alternative()`.176177Open [email-and-feeds.md](references/email-and-feeds.md) before maintaining custom mail classes,178multiple backend aliases, legacy MIME attachments, header validation, administrator addresses, or179feed stylesheets.180181## Implementation workflow1821831. Identify the affected topic and open its reference file.1842. Check both the current behavior and the next removal boundary.1853. Distinguish core support from backend-specific and opt-in capabilities.1864. Preserve async behavior when wrapping views, middleware, authentication, pagination, or tasks.1875. Run Django system checks and focused tests after changing extension points.1886. Test migrations against both model state and database state for state-only operations.1897. Test generated SQL and parameter types for custom ORM components.1908. Verify security headers, nonce uniqueness, redirects, content negotiation, and URL validation191 at the HTTP boundary.