Django 5.0: A Game-Changer for Modern Web Development
Explore the groundbreaking features of Django 5.0 and how they elevate modern web development.

Django 5.0 is here – what’s new?
Django 5.0: A Game-Changer for Modern Web Development
Django 5.0 is finally here! Released on December 4, 2023, this latest version of Django brings a host of new features, performance improvements, and backwards-incompatible changes that developers should be aware of. If you’re upgrading from Django 4.2 or earlier, this guide will walk you through the most exciting updates and help you transition smoothly.

Python Compatibility in Django 5.0
Django 5.0 officially supports:
- Python 3.10, 3.11, and 3.12
- Django 4.2.x is the last version to support Python 3.8 and 3.9
Key Features in Django 5.0
1. Facet Filters in the Django Admin
The Django admin now displays facet counts for applied filters. This feature enhances usability and can be toggled using the ModelAdmin.show_facets
attribute.
2. Simplified Form Field Rendering
Django 5.0 introduces field groups, which allow you to streamline form rendering. Instead of manually structuring form elements like labels, widgets, and errors, you can now use .as_field_group()
.
Before Django 5.0:
<form>
<div>
{{ form.name.label_tag }}
{{ form.name.help_text }}
{{ form.name.errors }}
{{ form.name }}
</div>
</form>
With Django 5.0:
<form>
<div>
{{ form.name.as_field_group }}
</div>
</form>
3. Database-Computed Default Values
Django 5.0 introduces database-computed default values via the db_default
parameter, allowing values to be generated at the database level.
Example:
from django.db import models
from django.db.models.functions import Now
class MyModel(models.Model):
age = models.IntegerField(db_default=18)
created = models.DateTimeField(db_default=Now())
This offloads default value handling to the database, improving performance.
4. Generated Fields (Database Computed Columns)
Django now supports Generated Fields, allowing models to have database-generated columns.
Example:
from django.db import models
from django.db.models import F
class Square(models.Model):
side = models.IntegerField()
area = models.GeneratedField(
expression=F("side") * F("side"),
output_field=models.BigIntegerField(),
db_persist=True,
)
This ensures that the area
field is always computed based on the side
value.
5. Flexible Field Choices
Django 5.0 enhances Field.choices
by allowing:
- Mappings instead of a list of 2-tuples
- Callable functions for dynamic choices
- Direct enumeration usage (no need for
.choices
)
Example:
from django.db import models
Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")
SPORT_CHOICES = {
"Martial Arts": {"judo": "Judo", "karate": "Karate"},
"Racket": {"badminton": "Badminton", "tennis": "Tennis"},
}
def get_scores():
return [(i, str(i)) for i in range(10)]
class Winner(models.Model):
name = models.CharField(max_length=100)
medal = models.CharField(max_length=20, choices=Medal) # No `.choices` needed
sport = models.CharField(max_length=50, choices=SPORT_CHOICES)
score = models.IntegerField(choices=get_scores) # Callable function allowed
This makes field choice declarations more intuitive and flexible.
Other Notable Improvements
Django Admin Updates
AdminSite.get_log_entries()
: Customize the queryset for log entries.- jQuery upgraded from 3.6.4 → 3.7.1
- XRegExp upgraded from 3.2.0 → 5.1.1
- Properties in
ModelAdmin.list_display
now support boolean attributes.
Authentication Updates
- PBKDF2 password hasher iteration count increased (from 600,000 to 720,000).
- New async functions:
aauthenticate()
,aget_user()
,alogin()
, etc. AuthenticationMiddleware
now providesHttpRequest.auser()
for async user retrieval.
Performance & Async Enhancements
- Async signal dispatch:
Signal.asend()
andSignal.asend_robust()
QuerySet.aiterator()
now supports prefetching- New async shortcuts:
aget_object_or_404()
,aget_list_or_404()
Internationalization
- Uyghur language support added.
Breaking Changes & Deprecations
1. Dropped Support for MySQL < 8.0.11
Django 5.0 now requires MySQL 8.0.11 or higher. If you’re using an older MySQL version, an upgrade is necessary.
2. UUIDField Migration on MariaDB 10.7+
Django now stores UUID fields natively as UUID
columns instead of CHAR(32)
. If migrating from Django < 5.0, you need to subclass UUIDField
:
Solution:
class Char32UUIDField(models.UUIDField):
def db_type(self, connection):
return "char(32)"
def get_db_prep_value(self, value, connection, prepared=False):
value = super().get_db_prep_value(value, connection, prepared)
return value.hex if value else value
Then update your models accordingly.
3. Removed Google Sitemaps Ping
Django 5.0 removes django.contrib.sitemaps.ping_google()
as Google’s Sitemaps ping endpoint is deprecated.
Should You Upgrade to Django 5.0?
If you’re using Django 4.2 or earlier, upgrading to Django 5.0 brings better performance, improved async support, and cleaner code structures. However, ensure:
- Your project does not depend on deprecated features.
- Your database supports the new changes (especially MySQL/MariaDB users).
- You’re using Python 3.10+.
If your stack is compatible, upgrading is highly recommended.
Conclusion
Django 5.0 is packed with powerful new features, performance enhancements, and critical updates for modern web applications. With simpler form rendering, async improvements, and database enhancements, it provides an even more efficient and developer-friendly experience.
Are you planning to upgrade? Share your thoughts in the comments below!
