django-rest-framework/community/3.12-announcement/index.html

3171 lines
58 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Django REST framework - Web APIs for Django">
<link rel="canonical" href="https://www.django-rest-framework.org/community/3.12-announcement/">
<link rel="prev" href="../3.13-announcement/">
<link rel="next" href="../3.11-announcement/">
<link rel="icon" href="../../theme/img/favicon.ico">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.3">
<title>3.12 Announcement - Django REST framework</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.484c7ddc.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../theme/stylesheets/extra.css">
<link rel="stylesheet" href="../../theme/stylesheets/prettify.css">
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="custom" data-md-color-accent="custom">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#django-rest-framework-312" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="Django REST framework" class="md-header__button md-logo" aria-label="Django REST framework" data-md-component="logo">
<img src="../../theme/img/logo.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Django REST framework
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
3.12 Announcement
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme)" data-md-color-scheme="default" data-md-color-primary="custom" data-md-color-accent="custom" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m14.3 16-.7-2h-3.2l-.7 2H7.8L11 7h2l3.2 9zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12zm-9.15 3.96h2.3L12 9z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="custom" data-md-color-accent="custom" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="custom" data-md-color-accent="custom" aria-label="Switch to system preference" type="radio" name="__palette" id="__palette_2">
<label class="md-header__button md-icon" title="Switch to system preference" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/encode/django-rest-framework" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../.." class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../tutorial/quickstart/" class="md-tabs__link">
Tutorial
</a>
</li>
<li class="md-tabs__item">
<a href="../../api-guide/requests/" class="md-tabs__link">
API Guide
</a>
</li>
<li class="md-tabs__item">
<a href="../../topics/documenting-your-api/" class="md-tabs__link">
Topics
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../tutorials-and-resources/" class="md-tabs__link">
Community
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="Django REST framework" class="md-nav__button md-logo" aria-label="Django REST framework" data-md-component="logo">
<img src="../../theme/img/logo.png" alt="logo">
</a>
Django REST framework
</label>
<div class="md-nav__source">
<a href="https://github.com/encode/django-rest-framework" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Tutorial
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Tutorial
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../tutorial/quickstart/" class="md-nav__link">
<span class="md-ellipsis">
Quickstart
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/1-serialization/" class="md-nav__link">
<span class="md-ellipsis">
1 - Serialization
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/2-requests-and-responses/" class="md-nav__link">
<span class="md-ellipsis">
2 - Requests and responses
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/3-class-based-views/" class="md-nav__link">
<span class="md-ellipsis">
3 - Class based views
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/4-authentication-and-permissions/" class="md-nav__link">
<span class="md-ellipsis">
4 - Authentication and permissions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/5-relationships-and-hyperlinked-apis/" class="md-nav__link">
<span class="md-ellipsis">
5 - Relationships and hyperlinked APIs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tutorial/6-viewsets-and-routers/" class="md-nav__link">
<span class="md-ellipsis">
6 - Viewsets and routers
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
API Guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
API Guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../api-guide/requests/" class="md-nav__link">
<span class="md-ellipsis">
Requests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/responses/" class="md-nav__link">
<span class="md-ellipsis">
Responses
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/views/" class="md-nav__link">
<span class="md-ellipsis">
Views
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/generic-views/" class="md-nav__link">
<span class="md-ellipsis">
Generic views
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/viewsets/" class="md-nav__link">
<span class="md-ellipsis">
Viewsets
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/routers/" class="md-nav__link">
<span class="md-ellipsis">
Routers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/parsers/" class="md-nav__link">
<span class="md-ellipsis">
Parsers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/renderers/" class="md-nav__link">
<span class="md-ellipsis">
Renderers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/serializers/" class="md-nav__link">
<span class="md-ellipsis">
Serializers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/fields/" class="md-nav__link">
<span class="md-ellipsis">
Serializer fields
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/relations/" class="md-nav__link">
<span class="md-ellipsis">
Serializer relations
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/validators/" class="md-nav__link">
<span class="md-ellipsis">
Validators
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/authentication/" class="md-nav__link">
<span class="md-ellipsis">
Authentication
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/permissions/" class="md-nav__link">
<span class="md-ellipsis">
Permissions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/caching/" class="md-nav__link">
<span class="md-ellipsis">
Caching
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/throttling/" class="md-nav__link">
<span class="md-ellipsis">
Throttling
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/filtering/" class="md-nav__link">
<span class="md-ellipsis">
Filtering
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/pagination/" class="md-nav__link">
<span class="md-ellipsis">
Pagination
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/versioning/" class="md-nav__link">
<span class="md-ellipsis">
Versioning
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/content-negotiation/" class="md-nav__link">
<span class="md-ellipsis">
Content negotiation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/metadata/" class="md-nav__link">
<span class="md-ellipsis">
Metadata
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/schemas/" class="md-nav__link">
<span class="md-ellipsis">
Schemas
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/format-suffixes/" class="md-nav__link">
<span class="md-ellipsis">
Format suffixes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/reverse/" class="md-nav__link">
<span class="md-ellipsis">
Returning URLs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/exceptions/" class="md-nav__link">
<span class="md-ellipsis">
Exceptions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/status-codes/" class="md-nav__link">
<span class="md-ellipsis">
Status codes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/testing/" class="md-nav__link">
<span class="md-ellipsis">
Testing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../api-guide/settings/" class="md-nav__link">
<span class="md-ellipsis">
Settings
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Topics
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Topics
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../topics/documenting-your-api/" class="md-nav__link">
<span class="md-ellipsis">
Documenting your API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/internationalization/" class="md-nav__link">
<span class="md-ellipsis">
Internationalization
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/ajax-csrf-cors/" class="md-nav__link">
<span class="md-ellipsis">
AJAX, CSRF & CORS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/html-and-forms/" class="md-nav__link">
<span class="md-ellipsis">
HTML & Forms
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/browser-enhancements/" class="md-nav__link">
<span class="md-ellipsis">
Browser Enhancements
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/browsable-api/" class="md-nav__link">
<span class="md-ellipsis">
The Browsable API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../topics/rest-hypermedia-hateoas/" class="md-nav__link">
<span class="md-ellipsis">
REST, Hypermedia & HATEOAS
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
Community
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Community
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tutorials-and-resources/" class="md-nav__link">
<span class="md-ellipsis">
Tutorials and Resources
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../third-party-packages/" class="md-nav__link">
<span class="md-ellipsis">
Third Party Packages
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Contributing to REST framework
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../project-management/" class="md-nav__link">
<span class="md-ellipsis">
Project management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../release-notes/" class="md-nav__link">
<span class="md-ellipsis">
Release Notes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.16-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.16 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.15-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.15 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.14-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.14 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.13-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.13 Announcement
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
3.12 Announcement
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
3.12 Announcement
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#grouping-operations-with-tags" class="md-nav__link">
<span class="md-ellipsis">
Grouping operations with tags.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#customizing-the-operation-id" class="md-nav__link">
<span class="md-ellipsis">
Customizing the operation ID.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#support-for-openapi-components" class="md-nav__link">
<span class="md-ellipsis">
Support for OpenAPI components.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#more-public-api" class="md-nav__link">
<span class="md-ellipsis">
More Public API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#support-for-jsonfield" class="md-nav__link">
<span class="md-ellipsis">
Support for JSONField.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#searchfilter-improvements" class="md-nav__link">
<span class="md-ellipsis">
SearchFilter improvements
</span>
</a>
<nav class="md-nav" aria-label="SearchFilter improvements">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nested-searches-against-jsonfield-and-hstorefield" class="md-nav__link">
<span class="md-ellipsis">
Nested searches against JSONField and HStoreField
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#searches-against-annotate-fields" class="md-nav__link">
<span class="md-ellipsis">
Searches against annotate fields
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#deprecations" class="md-nav__link">
<span class="md-ellipsis">
Deprecations
</span>
</a>
<nav class="md-nav" aria-label="Deprecations">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#serializersnullbooleanfield" class="md-nav__link">
<span class="md-ellipsis">
serializers.NullBooleanField
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#funding" class="md-nav__link">
<span class="md-ellipsis">
Funding
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../3.11-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.11 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.10-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.10 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.9-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.9 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.8-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.8 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.7-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.7 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.6-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.6 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.5-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.5 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.4-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.4 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.3-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.3 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.2-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.2 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.1-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.1 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../3.0-announcement/" class="md-nav__link">
<span class="md-ellipsis">
3.0 Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../kickstarter-announcement/" class="md-nav__link">
<span class="md-ellipsis">
Kickstarter Announcement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../mozilla-grant/" class="md-nav__link">
<span class="md-ellipsis">
Mozilla Grant
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
Jobs
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#grouping-operations-with-tags" class="md-nav__link">
<span class="md-ellipsis">
Grouping operations with tags.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#customizing-the-operation-id" class="md-nav__link">
<span class="md-ellipsis">
Customizing the operation ID.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#support-for-openapi-components" class="md-nav__link">
<span class="md-ellipsis">
Support for OpenAPI components.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#more-public-api" class="md-nav__link">
<span class="md-ellipsis">
More Public API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#support-for-jsonfield" class="md-nav__link">
<span class="md-ellipsis">
Support for JSONField.
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#searchfilter-improvements" class="md-nav__link">
<span class="md-ellipsis">
SearchFilter improvements
</span>
</a>
<nav class="md-nav" aria-label="SearchFilter improvements">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#nested-searches-against-jsonfield-and-hstorefield" class="md-nav__link">
<span class="md-ellipsis">
Nested searches against JSONField and HStoreField
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#searches-against-annotate-fields" class="md-nav__link">
<span class="md-ellipsis">
Searches against annotate fields
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#deprecations" class="md-nav__link">
<span class="md-ellipsis">
Deprecations
</span>
</a>
<nav class="md-nav" aria-label="Deprecations">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#serializersnullbooleanfield" class="md-nav__link">
<span class="md-ellipsis">
serializers.NullBooleanField
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#funding" class="md-nav__link">
<span class="md-ellipsis">
Funding
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<nav class="md-path" aria-label="Navigation" >
<ol class="md-path__list">
<li class="md-path__item">
<a href="../.." class="md-path__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-path__item">
<a href="../tutorials-and-resources/" class="md-path__link">
<span class="md-ellipsis">
Community
</span>
</a>
</li>
</ol>
</nav>
<article class="md-content__inner md-typeset">
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
<h1 id="django-rest-framework-312">Django REST framework 3.12<a class="headerlink" href="#django-rest-framework-312" title="Permanent link">&para;</a></h1>
<p>REST framework 3.12 brings a handful of refinements to the OpenAPI schema
generation, plus support for Django's new database-agnostic <code>JSONField</code>,
and some improvements to the <code>SearchFilter</code> class.</p>
<h2 id="grouping-operations-with-tags">Grouping operations with tags.<a class="headerlink" href="#grouping-operations-with-tags" title="Permanent link">&para;</a></h2>
<p>Open API schemas will now automatically include tags, based on the first element
in the URL path.</p>
<p>For example...</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Path</th>
<th>Tags</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GET</code>, <code>PUT</code>, <code>PATCH</code>, <code>DELETE</code></td>
<td><code>/users/{id}/</code></td>
<td><code>['users']</code></td>
</tr>
<tr>
<td><code>GET</code>, <code>POST</code></td>
<td><code>/users/</code></td>
<td><code>['users']</code></td>
</tr>
<tr>
<td><code>GET</code>, <code>PUT</code>, <code>PATCH</code>, <code>DELETE</code></td>
<td><code>/orders/{id}/</code></td>
<td><code>['orders']</code></td>
</tr>
<tr>
<td><code>GET</code>, <code>POST</code></td>
<td><code>/orders/</code></td>
<td><code>['orders']</code></td>
</tr>
</tbody>
</table>
<p>The tags used for a particular view may also be overridden...</p>
<div class="language-python highlight"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">MyOrders</span><span class="p">(</span><span class="n">APIView</span><span class="p">):</span>
<span class="n">schema</span> <span class="o">=</span> <span class="n">AutoSchema</span><span class="p">(</span><span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;users&quot;</span><span class="p">,</span> <span class="s2">&quot;orders&quot;</span><span class="p">])</span>
<span class="o">...</span>
</code></pre></div>
<p>See <a href="https://www.django-rest-framework.org/api-guide/schemas/#grouping-operations-with-tags">the schema documentation</a> for more information.</p>
<h2 id="customizing-the-operation-id">Customizing the operation ID.<a class="headerlink" href="#customizing-the-operation-id" title="Permanent link">&para;</a></h2>
<p>REST framework automatically determines operation IDs to use in OpenAPI
schemas. The latest version provides more control for overriding the behavior
used to generate the operation IDs.</p>
<p>See <a href="https://www.django-rest-framework.org/api-guide/schemas/#operationid">the schema documentation</a> for more information.</p>
<h2 id="support-for-openapi-components">Support for OpenAPI components.<a class="headerlink" href="#support-for-openapi-components" title="Permanent link">&para;</a></h2>
<p>In order to output more graceful OpenAPI schemes, REST framework 3.12 now
defines components in the schema, and then references them inside request
and response objects. This is in contrast with the previous approach, which
fully expanded the request and response bodies for each operation.</p>
<p>The names used for a component default to using the serializer class name, <a href="https://www.django-rest-framework.org/api-guide/schemas/#components">but
may be overridden if needed</a>...</p>
<div class="language-python highlight"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">MyOrders</span><span class="p">(</span><span class="n">APIView</span><span class="p">):</span>
<span class="n">schema</span> <span class="o">=</span> <span class="n">AutoSchema</span><span class="p">(</span><span class="n">component_name</span><span class="o">=</span><span class="s2">&quot;OrderDetails&quot;</span><span class="p">)</span>
</code></pre></div>
<h2 id="more-public-api">More Public API<a class="headerlink" href="#more-public-api" title="Permanent link">&para;</a></h2>
<p>Many methods on the <code>AutoSchema</code> class have now been promoted to public API,
allowing you to more fully customize the schema generation. The following methods
are now available for overriding...</p>
<ul>
<li><code>get_path_parameters</code></li>
<li><code>get_pagination_parameters</code></li>
<li><code>get_filter_parameters</code></li>
<li><code>get_request_body</code></li>
<li><code>get_responses</code></li>
<li><code>get_serializer</code></li>
<li><code>get_paginator</code></li>
<li><code>map_serializer</code></li>
<li><code>map_field</code></li>
<li><code>map_choice_field</code></li>
<li><code>map_field_validators</code></li>
<li><code>allows_filters</code>.</li>
</ul>
<p>See <a href="https://www.django-rest-framework.org/api-guide/schemas/#per-view-customization">the schema docs</a>
for details on using custom <code>AutoSchema</code> subclasses.</p>
<h2 id="support-for-jsonfield">Support for JSONField.<a class="headerlink" href="#support-for-jsonfield" title="Permanent link">&para;</a></h2>
<p>Django 3.1 deprecated the existing <code>django.contrib.postgres.fields.JSONField</code>
in favor of a new database-agnositic <code>JSONField</code>.</p>
<p>REST framework 3.12 now supports this new model field, and <code>ModelSerializer</code>
classes will correctly map the model field.</p>
<h2 id="searchfilter-improvements">SearchFilter improvements<a class="headerlink" href="#searchfilter-improvements" title="Permanent link">&para;</a></h2>
<p>There are a couple of significant improvements to the <code>SearchFilter</code> class.</p>
<h3 id="nested-searches-against-jsonfield-and-hstorefield">Nested searches against JSONField and HStoreField<a class="headerlink" href="#nested-searches-against-jsonfield-and-hstorefield" title="Permanent link">&para;</a></h3>
<p>The class now supports nested search within <code>JSONField</code> and <code>HStoreField</code>, using
the double underscore notation for traversing which element of the field the
search should apply to.</p>
<div class="language-python highlight"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">SitesSearchView</span><span class="p">(</span><span class="n">generics</span><span class="o">.</span><span class="n">ListAPIView</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> An API view to return a list of archaeological sites, optionally filtered</span>
<span class="sd"> by a search against the site name or location. (Location searches are</span>
<span class="sd"> matched against the region and country names.)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">queryset</span> <span class="o">=</span> <span class="n">Sites</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="n">serializer_class</span> <span class="o">=</span> <span class="n">SitesSerializer</span>
<span class="n">filter_backends</span> <span class="o">=</span> <span class="p">[</span><span class="n">filters</span><span class="o">.</span><span class="n">SearchFilter</span><span class="p">]</span>
<span class="n">search_fields</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;site_name&quot;</span><span class="p">,</span> <span class="s2">&quot;location__region&quot;</span><span class="p">,</span> <span class="s2">&quot;location__country&quot;</span><span class="p">]</span>
</code></pre></div>
<h3 id="searches-against-annotate-fields">Searches against annotate fields<a class="headerlink" href="#searches-against-annotate-fields" title="Permanent link">&para;</a></h3>
<p>Django allows querysets to create additional virtual fields, using the <code>.annotate</code>
method. We now support searching against annotate fields.</p>
<div class="language-python highlight"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">PublisherSearchView</span><span class="p">(</span><span class="n">generics</span><span class="o">.</span><span class="n">ListAPIView</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Search for publishers, optionally filtering the search against the average</span>
<span class="sd"> rating of all their books.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">queryset</span> <span class="o">=</span> <span class="n">Publisher</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span><span class="n">avg_rating</span><span class="o">=</span><span class="n">Avg</span><span class="p">(</span><span class="s2">&quot;book__rating&quot;</span><span class="p">))</span>
<span class="n">serializer_class</span> <span class="o">=</span> <span class="n">PublisherSerializer</span>
<span class="n">filter_backends</span> <span class="o">=</span> <span class="p">[</span><span class="n">filters</span><span class="o">.</span><span class="n">SearchFilter</span><span class="p">]</span>
<span class="n">search_fields</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;avg_rating&quot;</span><span class="p">]</span>
</code></pre></div>
<hr />
<h2 id="deprecations">Deprecations<a class="headerlink" href="#deprecations" title="Permanent link">&para;</a></h2>
<h3 id="serializersnullbooleanfield"><code>serializers.NullBooleanField</code><a class="headerlink" href="#serializersnullbooleanfield" title="Permanent link">&para;</a></h3>
<p><code>serializers.NullBooleanField</code> is now pending deprecation, and will be removed in 3.14.</p>
<p>Instead use <code>serializers.BooleanField</code> field and set <code>allow_null=True</code> which does the same thing.</p>
<hr />
<h2 id="funding">Funding<a class="headerlink" href="#funding" title="Permanent link">&para;</a></h2>
<p>REST framework is a <em>collaboratively funded project</em>. If you use
REST framework commercially we strongly encourage you to invest in its
continued development by <strong><a href="https://opencollective.com/django-rest-framework">signing up for a paid plan</a></strong>.</p>
<p><em>Every single sign-up helps us make REST framework long-term financially sustainable.</em></p>
<ul class="premium-promo promo">
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?utm_source=drf&utm_medium=banner&utm_campaign=drf" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/stream-130.png)">Stream</a></li>
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless-plus-text.png)">Kloudless</a></li>
<li><a href="https://lightsonsoftware.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/lightson-dark.png)">Lights On Software</a></li>
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
<p><em>Many thanks to all our <a href="https://fund.django-rest-framework.org/topics/funding/#our-sponsors">wonderful sponsors</a>, and in particular to our premium backers, <a href="https://getsentry.com/welcome/">Sentry</a>, <a href="https://getstream.io/?utm_source=drf&amp;utm_medium=banner&amp;utm_campaign=drf">Stream</a>, <a href="https://software.esg-usa.com/">ESG</a>, <a href="https://rollbar.com/?utm_source=django&amp;utm_medium=sponsorship&amp;utm_campaign=freetrial">Rollbar</a>, <a href="https://cadre.com">Cadre</a>, <a href="https://hubs.ly/H0f30Lf0">Kloudless</a>, <a href="https://lightsonsoftware.com">Lights On Software</a>, and <a href="https://retool.com/?utm_source=djangorest&amp;utm_medium=sponsorship">Retool</a>.</em></p>
</article>
</div>
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<script id="__config" type="application/json">{"annotate": null, "base": "../..", "features": ["content.tabs.link", "content.code.annotate", "content.code.copy", "navigation.tabs", "navigation.tabs.sticky", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.sections", "navigation.top", "navigation.tracking", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../assets/javascripts/bundle.79ae519e.min.js"></script>
<script src="../../theme/js/prettify-1.0.js"></script>
<script>
document$.subscribe(function() {
document.querySelectorAll('pre code').forEach(code => {
code.parentElement.classList.add('prettyprint', 'well');
});
prettyPrint();
});
</script>
</body>
</html>