Skip to main content

Django REST Framework 3.15

Released on March 15th, 2024 with 176 commits by 138 authors
At the Internet, on March 15th, 2024, with 176 commits by 138 authors, we are happy to announce the release of Django REST framework 3.15.

Django 5.0 and Python 3.12 Support

The latest release now fully supports Django 5.0 and Python 3.12.

Django Support

Minimum: Django 3.0
Latest: Django 5.0

Python Support

Minimum: Python 3.6
Latest: Python 3.12

Primary Support of UniqueConstraint

ModelSerializer now generates validators for UniqueConstraint, including both UniqueValidator and UniqueTogetherValidator.

Example

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    sku = models.CharField(max_length=50)
    
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['sku'],
                name='unique_sku'
            )
        ]
The serializer will automatically generate the appropriate validators:
from rest_framework import serializers

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'sku']
    # Validators for UniqueConstraint are automatically generated!

SimpleRouter Non-Regex Matching Support

By default the URLs created by SimpleRouter use regular expressions. This behavior can be modified by setting the use_regex_path argument to False when instantiating the router.
from rest_framework.routers import SimpleRouter

router = SimpleRouter()  # Uses regex by default
router.register(r'users', UserViewSet)
Using path converters instead of regex can make your URLs cleaner and more maintainable.

ZoneInfo as the Primary Source of Timezone Data

Dependency on pytz has been removed and deprecation warnings have been added. Django will provide ZoneInfo instances as long as USE_DEPRECATED_PYTZ is not enabled.
Migration Required:If you were using pytz directly in your code, you’ll need to migrate to using ZoneInfo. More info on the migration can be found in this guide.

Example Migration

import pytz
from datetime import datetime

tz = pytz.timezone('America/New_York')
aware_dt = tz.localize(datetime(2024, 3, 15, 12, 0, 0))
Searches now may contain quoted phrases with spaces, where each phrase is considered as a single search term.

Example

from rest_framework import filters

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    filter_backends = [filters.SearchFilter]
    search_fields = ['title', 'content']
Now you can search with:

Simple Search

/api/articles/?search=django
Searches for “django”

Quoted Phrases

/api/articles/?search="django rest"
Searches for the exact phrase “django rest”

Multiple Terms

/api/articles/?search=django,python
Searches for “django” OR “python”

Combined

/api/articles/?search="django rest",python
Searches for “django rest” OR “python”
The search will now raise a validation error if any null-character is provided in the search query.
See the Filtering API guide for more information.

Browsable API Security Improvement

The browsable API now uses POST method instead of GET to perform logout. This prevents CSRF attacks that could force users to log out.
Why this matters:Using GET for state-changing operations (like logout) is a security anti-pattern. An attacker could create a malicious link that logs users out when clicked. Using POST prevents this attack vector.

Other Fixes and Improvements

There are a number of fixes and minor improvements in this release:
  • jQuery upgraded to 3.7.1
  • Use str as default path converter
  • Document support for http.HTTPMethod in @action decorator (Python 3.11+)
  • Partial serializers should not have required fields
  • Propagate ‘default’ from model field to serializer field
  • Allow to override child.run_validation call in ListSerializer
  • Fix choices in ChoiceField to support IntEnum
  • Fix SearchFilter rendering search field with invalid value
  • Fix OpenAPI Schema yaml rendering for timedelta
  • Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespaces
  • Fixes BrowsableAPIRenderer for usage with ListSerializer
  • Fix URLPathVersioning reverse fallback
  • Allow Request, Response, Field, and GenericAPIView to be subscriptable
  • This enables making classes generic for type checking
  • Example: GenericAPIView[MyModel]
  • Fix pagination response schemas
  • Removed usage of field.choices that triggered full table load
  • Handle Nested Relation in SlugRelatedField when many=False
  • Use PrimaryKeyRelatedField pkfield in OpenAPI
  • Remove inline CSS
  • Add CSP nonce where available
  • Make browsable API compatible with strong CSP
  • Avoid inline script execution for CSRF token injection

Complete Release Notes

See the release notes page for a complete listing of all changes.

Upgrading

To upgrade to Django REST Framework 3.15:
pip install -U djangorestframework
Important Changes:
  • If you’re using pytz, migrate to ZoneInfo
  • Logout in browsable API now uses POST instead of GET
  • SearchFilter behavior has changed to support quoted phrases
  • Several deprecated features have been removed

Community Growth

This release represents significant community involvement:

176 Commits

Total commits in this release

138 Authors

Contributors to this release

Growing Ecosystem

Expanding third-party package support
Thank you to all the contributors who made this release possible! Your contributions, whether code, documentation, or community support, are invaluable to the Django REST Framework project.

Full Changelog

View all changes on GitHub

PyPI Release

Download from PyPI

Migration Guide

PyTZ to ZoneInfo migration

Discussion Group

Join the community

Build docs developers (and LLMs) love