<p>The 3.9 release gives access to <em>extra actions</em> in the Browsable API, introduces composable permissions and built-in <ahref="https://www.openapis.org/">OpenAPI</a> schema support. (Formerly known as Swagger)</p>
<p>If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by
<strong><ahref="../funding/">signing up for a paid plan</a></strong>.</p>
<p><em>Many thanks to all our <ahref="https://fund.django-rest-framework.org/topics/funding/#our-sponsors">wonderful sponsors</a>, and in particular to our premium backers, <ahref="https://www.rover.com/careers/">Rover</a>, <ahref="https://sentry.io/welcome/">Sentry</a>, <ahref="https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf">Stream</a>, <ahref="https://auklet.io/">Auklet</a>, <ahref="https://rollbar.com">Rollbar</a>, <ahref="https://cadre.com">Cadre</a>, <ahref="https://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf">Load Impact</a>, and <ahref="https://hubs.ly/H0f30Lf0">Kloudless</a>.</em></p>
<p>REST framework now has a first-pass at directly including OpenAPI schema support. (Formerly known as Swagger)</p>
<p>Specifically:</p>
<ul>
<li>There are now <code>OpenAPIRenderer</code>, and <code>JSONOpenAPIRenderer</code> classes that deal with encoding <code>coreapi.Document</code> instances into OpenAPI YAML or OpenAPI JSON.</li>
<li>The <code>get_schema_view(...)</code> method now defaults to OpenAPI YAML, with CoreJSON as a secondary
option if it is selected via HTTP content negotiation.</li>
<li>There is a new management command <code>generateschema</code>, which you can use to dump
the schema into your repository.</li>
</ul>
<p>Here's an example of adding an OpenAPI schema to the URL conf:</p>
<p>You can now compose permission classes using the and/or operators, <code>&</code> and <code>|</code>.</p>
<p>For example...</p>
<pre><codeclass="python">permission_classes = [IsAuthenticated & (ReadOnly | IsAdmin)]
</code></pre>
<p>If you're using custom permission classes then make sure that you are subclassing
from <code>BasePermission</code> in order to enable this support.</p>
<h2id="viewset-extra-actions-available-in-the-browsable-api"><aclass="toclink"href="#viewset-extra-actions-available-in-the-browsable-api">ViewSet <em>Extra Actions</em> available in the Browsable API</a></h2>
<p>Following the introduction of the <code>action</code> decorator in v3.8, <em>extra actions</em> defined on a ViewSet are now available
from the Browsable API.</p>
<p><imgalt="Extra Actions displayed in the Browsable API"src="https://user-images.githubusercontent.com/2370209/32976956-1ca9ab7e-cbf1-11e7-981a-a20cb1e83d63.png"/></p>
<p>When defined, a dropdown of "Extra Actions", appropriately filtered to detail/non-detail actions, is displayed.</p>
<h3id="djangoobjectpermissionsfilter-moved-to-third-party-package"><aclass="toclink"href="#djangoobjectpermissionsfilter-moved-to-third-party-package"><code>DjangoObjectPermissionsFilter</code> moved to third-party package.</a></h3>
<p>The <code>DjangoObjectPermissionsFilter</code> class is pending deprecation, will be deprecated in 3.10 and removed entirely in 3.11.</p>
<p>It has been moved to the third-party <ahref="https://github.com/rpkilby/django-rest-framework-guardian"><code>djangorestframework-guardian</code></a>
package. Please use this instead.</p>
<h3id="router-argumentmethod-renamed-to-use-basename-for-consistency"><aclass="toclink"href="#router-argumentmethod-renamed-to-use-basename-for-consistency">Router argument/method renamed to use <code>basename</code> for consistency.</a></h3>
<ul>
<li>The <code>Router.register</code><code>base_name</code> argument has been renamed in favor of <code>basename</code>.</li>
<li>The <code>Router.get_default_base_name</code> method has been renamed in favor of <code>Router.get_default_basename</code>. <ahref="https://github.com/encode/django-rest-framework/pull/5990">#5990</a></li>
<p><code>base_name</code> and <code>get_default_base_name()</code> are pending deprecation. They will be deprecated in 3.10 and removed entirely in 3.11.</p>
<h3id="action-decorator-replaces-list_route-and-detail_route"><aclass="toclink"href="#action-decorator-replaces-list_route-and-detail_route"><code>action</code> decorator replaces <code>list_route</code> and <code>detail_route</code></a></h3>
<p>Both <code>list_route</code> and <code>detail_route</code> are now deprecated in favour of the single <code>action</code> decorator.
They will be removed entirely in 3.10.</p>
<p>The <code>action</code> decorator takes a boolean <code>detail</code> argument.</p>
<ul>
<li>Replace <code>detail_route</code> uses with <code>@action(detail=True)</code>.</li>
<li>Replace <code>list_route</code> uses with <code>@action(detail=False)</code>.</li>
<p>Both <code>APIView.exclude_from_schema</code> and the <code>exclude_from_schema</code> argument to the <code>@api_view</code> have now been removed.</p>
<p>For <code>APIView</code> you should instead set a <code>schema = None</code> attribute on the view class.</p>
<p>For function-based views the <code>@schema</code> decorator can be used to exclude the view from the schema, by using <code>@schema(None)</code>.</p>
<h2id="minor-fixes-and-improvements"><aclass="toclink"href="#minor-fixes-and-improvements">Minor fixes and improvements</a></h2>
<p>There are a large number of minor fixes and improvements in this release. See the <ahref="../release-notes/">release notes</a> page for a complete listing.</p>