Table of Contents
Here are the major new features and some important changes coming with Django 6.0. Django Project+2django.readthedocs.io+2
🔄 Background Tasks Framework (Built-in)
Django 6.0 includes a built-in tasks framework, making it possible to define background jobs directly — without requiring external dependencies like Celery (for simple use-cases). Django Project+2django.readthedocs.io+2
from django.tasks import task # or from django.core.tasks in some docs @task def send_welcome_email(user_id, subject, message): from django.contrib.auth import get_user_model User = get_user_model() user = User.objects.get(pk=user_id) user.email_user(subject, message) # To enqueue: send_welcome_email.enqueue( user_id=123, subject="Welcome!", message="Hello, thanks for joining." )
Important note: Django does not ship with a built-in worker that runs tasks out-of-the-box. You still need external infrastructure (e.g. your own worker process, Redis queue, or similar) to actually execute tasks. Django Project+1
So this is more like a standardised API in core for defining/queuing tasks; execution backend remains your responsibility.
🔐 Security & HTTP: Built-in Content Security Policy (CSP) support
Django 6.0 adds first-class support for the CSP standard — useful to prevent XSS or injection attacks. Now you can configure CSP headers globally via settings (or disable/override per view). Django Project+1
# settings.py from django.utils.csp import CSP SECURE_CSP = { "default-src": [CSP.SELF], "script-src": [CSP.SELF, CSP.NONCE], "img-src": [CSP.SELF, "https:"], } # optionally: # SECURE_CSP_REPORT_ONLY = True # to only report violations without blocking
This will cause Django to automatically add a Content-Security-Policy header with the configured rules to responses. Django Project+1
This is a great built-in alternative to third-party CSP packages — fewer dependencies and integrated into Django core.
🗃️ ORM, Models, Migrations, and Database Enhancements
There are many enhancements under the hood. Some of the most relevant:
- New aggregation/ORM functions:
- A new AnyValue aggregate — returns an arbitrary non-null value from input — supported on SQLite, MySQL, Oracle, and PostgreSQL 16+. Django Project+1
- StringAgg aggregate (concatenate values into a string with a delimiter), no longer PostgreSQL-only. Django Project+1
- You can now pass an order_by argument to Aggregate, and aggregate classes have a new allow_order_by attribute to control whether ordering is allowed. Django Project+1
- QuerySet.raw() now supports models with a CompositePrimaryKey. Also, subqueries that return a CompositePrimaryKey can be used with lookups beyond just __in (e.g. __exact). Django Project+1
- SQLite-specific improvement: JSONField now supports negative array indexing. Django Project+1
- For backends that support RETURNING (SQLite, PostgreSQL, Oracle), fields defined as GeneratedFields or fields assigned expressions are now refreshed from the database after save(). For backends that don’t support it (MySQL, MariaDB), Django will mark such fields as deferred so they’ll be refreshed on access. Django Project+1
- Some changes to migrations: squashed migrations themselves can be re-squashed (before being transitioned to normal migrations), improving database migration management. Also, migration serialization now supports more complex objects (e.g. zoneinfo.ZoneInfo, or deconstructible objects with “weird” keyword arg names). Django Project+1
These enhancements make the ORM more flexible and expressive, especially for complex queries and advanced database use-cases.
📧 Modern Email API
Email handling in Django is now upgraded to use Python’s modern email.message.EmailMessage API (introduced in Python 3.6). This improves Unicode support and offers a cleaner, more modern interface. Django Project+1
Example (simplified):
from django.core.mail import EmailMessage email = EmailMessage( subject="Hello", body="This is a test email.", from_email="no-reply@example.com", to=["user@example.com"], ) email.send()
If you used the older MIME-based approach, things should mostly work the same — but now you benefit from a more modern, future-proof email API.
📄 Template Enhancements: Template Partials & improved templating helpers
- Template Partials — you can now define and reuse small named fragments (partials) within a template file via {% partialdef %} and render them via {% partial %}. This helps make templates more modular and maintainable. Django Project+1
- Partials can also be referenced using template_name#partial_name for use with get_template(), {% include %}, etc. Django Project+1
- A few other improvements:
- Inside a {% for %} loop, a new variable forloop.length is now available — giving the total number of items in the loop. Django Project+1
- The querystring template tag now consistently prefixes the result with ?, and it accepts multiple mappings (e.g. dicts or QueryDicts), which improves reliability when generating query-strings. Django Project
Example use of partials (simplified):
{% partialdef "my_block" %} <div class="card"> <h2>{{ title }}</h2> <p>{{ content }}</p> </div> {% endpartialdef %} ... {% partial "my_block" with title="Hello", content="World!" %}
🛠️ Admin, Auth & Other Improvements
- In the admin interface: icons are now using Font Awesome Free 6.7.2 — gives a fresher look. Django Project+1
You can now customise the password-change form in admin using the AdminSite.password_change_form attribute. Example: # admin.py from django.contrib import admin from .forms import MyPasswordChangeForm class MyAdminSite(admin.AdminSite): password_change_form = MyPasswordChangeForm
- This gives more flexibility if you want to override default behavior. Django Project+1
- For authentication: the default iteration count for the PBKDF2 password hasher increases from 1,000,000 to 1,200,000 — a security hardening by default. Django Project+1
Other improvements involve geospatial support (GIS), PostgreSQL-specific enhancements, static files storage tweaks, and more — good for projects that use those features. Django Project+1
⚠️ Backwards-incompatible Changes & Removals
Because Django 6.0 is a “feature release”, some previously deprecated APIs are now removed. Upgrading may require some code changes. Key removals/changes: Django Project+1
- Some legacy form renderers are removed: DjangoDivFormRenderer and Jinja2DivFormRenderer are gone. Django Project+1
- The ability to pass positional arguments to BaseConstraint is removed. Django Project+1
- In the database backend APIs: certain methods have been renamed (e.g. return_insert_columns() → returning_columns(), and fetch_returned_insert_rows() → fetch_returned_rows()), to unify behavior for both INSERT … RETURNING and UPDATE … RETURNING. Django Project+1
- Some shortcut/fallback behaviors related to ForeignObject / ForeignObjectRel and Join internals are removed — e.g. no fallback to get_joining_columns(). Django Project+1
- Default scheme for forms.URLField has changed from “http” to “https” (so URLFields will assume secure URLs by default). Django Project+1
If your project relies on any of these removed behaviors, be sure to update accordingly when upgrading.
🧪 What’s Not Guaranteed — Depends on What Landed by Alpha Freeze
According to the official roadmap, only features merged into main by the alpha-freeze date (Sept 17) will make it into Django 6.0. Django Project+1
So: while the new CSP support, template partials, tasks framework, email API, and many ORM/admin enhancements are listed in the release notes as “what’s new”, it’s possible that some smaller or more experimental features proposed — but not committed by freeze — may get deferred to 6.1 or later. Django Project+1
✅ What This Means for You (As a Django Developer)
Since you (the user) do Django / web-development:
- If you upgrade to Django 6.0 (once released), you get built-in CSP, modern email API, easier background task definitions, template partials, more powerful ORM features. That can simplify your stack (less third-party dependencies) and make code more modern and secure.
- However, you need to audit your codebase for deprecated/removed APIs (especially database backend customizations, URLFields, old form renderers, positional constraint usage, etc.) before upgrading.
- If using third-party apps, check compatibility — after 6.0, many of those packages will likely drop support for older Django versions (< 5.2). Django Project+1
- For background tasks: while the API is built-in, you still need to supply/maintain worker infrastructure (e.g. Celery or custom worker) for production. For light / dev-use this may already be enough.