Deployed e221d9a with MkDocs version: 1.6.0

This commit is contained in:
2025-12-12 11:53:29 +00:00
parent d1bb692f4b
commit d39e3406d1
25 changed files with 260 additions and 192 deletions

View File

@ -562,10 +562,11 @@
<p>Authentication always runs at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.</p>
<p>The <code>request.user</code> property will typically be set to an instance of the <code>contrib.auth</code> package's <code>User</code> class.</p>
<p>The <code>request.auth</code> property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.</p>
<hr />
<p><strong>Note:</strong> Don't forget that <strong>authentication by itself won't allow or disallow an incoming request</strong>, it simply identifies the credentials that the request was made with.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Don't forget that <strong>authentication by itself won't allow or disallow an incoming request</strong>, it simply identifies the credentials that the request was made with.</p>
<p>For information on how to set up the permission policies for your API please see the <a href="../permissions/">permissions documentation</a>.</p>
<hr />
</div>
<h2 id="how-authentication-is-determined"><a class="toclink" href="#how-authentication-is-determined">How authentication is determined</a></h2>
<p>The authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set <code>request.user</code> and <code>request.auth</code> using the return value of the first class that successfully authenticates.</p>
<p>If no class authenticates, <code>request.user</code> will be set to an instance of <code>django.contrib.auth.models.AnonymousUser</code>, and <code>request.auth</code> will be set to <code>None</code>.</p>
@ -638,12 +639,16 @@ WSGIPassAuthorization On
<p>Unauthenticated responses that are denied permission will result in an <code>HTTP 401 Unauthorized</code> response with an appropriate WWW-Authenticate header. For example:</p>
<pre><code>WWW-Authenticate: Basic realm="api"
</code></pre>
<p><strong>Note:</strong> If you use <code>BasicAuthentication</code> in production you must ensure that your API is only available over <code>https</code>. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you use <code>BasicAuthentication</code> in production you must ensure that your API is only available over <code>https</code>. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.</p>
</div>
<h2 id="tokenauthentication"><a class="toclink" href="#tokenauthentication">TokenAuthentication</a></h2>
<hr />
<p><strong>Note:</strong> The token authentication provided by Django REST framework is a fairly simple implementation.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The token authentication provided by Django REST framework is a fairly simple implementation.</p>
<p>For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the <a href="https://github.com/James1345/django-rest-knox">Django REST Knox</a> third party package.</p>
<hr />
</div>
<p>This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.</p>
<p>To use the <code>TokenAuthentication</code> scheme you'll need to <a href="#setting-the-authentication-scheme">configure the authentication classes</a> to include <code>TokenAuthentication</code>, and additionally include <code>rest_framework.authtoken</code> in your <code>INSTALLED_APPS</code> setting:</p>
<pre><code>INSTALLED_APPS = [
@ -674,9 +679,10 @@ print(token.key)
<p>The <code>curl</code> command line tool may be useful for testing token authenticated APIs. For example:</p>
<pre><code>curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
</code></pre>
<hr />
<p><strong>Note:</strong> If you use <code>TokenAuthentication</code> in production you must ensure that your API is only available over <code>https</code>.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you use <code>TokenAuthentication</code> in production you must ensure that your API is only available over <code>https</code>.</p>
</div>
<h3 id="generating-tokens"><a class="toclink" href="#generating-tokens">Generating Tokens</a></h3>
<h4 id="by-using-signals"><a class="toclink" href="#by-using-signals">By using signals</a></h4>
<p>If you want every user to have an automatically generated Token, you can simply catch the User's <code>post_save</code> signal.</p>
@ -795,9 +801,10 @@ already exist. To change this and other behavior, consult the
</ul>
<p>You <em>may</em> also override the <code>.authenticate_header(self, request)</code> method. If implemented, it should return a string that will be used as the value of the <code>WWW-Authenticate</code> header in a <code>HTTP 401 Unauthorized</code> response.</p>
<p>If the <code>.authenticate_header()</code> method is not overridden, the authentication scheme will return <code>HTTP 403 Forbidden</code> responses when an unauthenticated request is denied access.</p>
<hr />
<p><strong>Note:</strong> When your custom authenticator is invoked by the request object's <code>.user</code> or <code>.auth</code> properties, you may see an <code>AttributeError</code> re-raised as a <code>WrappedAttributeError</code>. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the <code>AttributeError</code> originates from your custom authenticator and will instead assume that the request object does not have a <code>.user</code> or <code>.auth</code> property. These errors should be fixed or otherwise handled by your authenticator.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When your custom authenticator is invoked by the request object's <code>.user</code> or <code>.auth</code> properties, you may see an <code>AttributeError</code> re-raised as a <code>WrappedAttributeError</code>. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the <code>AttributeError</code> originates from your custom authenticator and will instead assume that the request object does not have a <code>.user</code> or <code>.auth</code> property. These errors should be fixed or otherwise handled by your authenticator.</p>
</div>
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
<p>The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X-USERNAME'.</p>
<pre><code>from django.contrib.auth.models import User

View File

@ -512,8 +512,10 @@ def get_user_list(request):
content = {&quot;user_feed&quot;: request.user.get_user_feed()}
return Response(content)
</code></pre>
<p><strong>NOTE:</strong> The <a href="https://docs.djangoproject.com/en/stable/topics/cache/#the-per-view-cache"><code>cache_page</code></a> decorator only caches the
<code>GET</code> and <code>HEAD</code> responses with status 200.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <a href="https://docs.djangoproject.com/en/stable/topics/cache/#the-per-view-cache"><code>cache_page</code></a> decorator only caches the <code>GET</code> and <code>HEAD</code> responses with status 200.</p>
</div>
</div> <!--/span-->

View File

@ -479,10 +479,11 @@
</ul>
<p>If the requested view was only configured with renderers for <code>YAML</code> and <code>HTML</code>, then REST framework would select whichever renderer was listed first in the <code>renderer_classes</code> list or <code>DEFAULT_RENDERER_CLASSES</code> setting.</p>
<p>For more information on the <code>HTTP Accept</code> header, see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616</a></p>
<hr />
<p><strong>Note</strong>: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>"q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.</p>
<p>This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.</p>
<hr />
</div>
<h1 id="custom-content-negotiation"><a class="toclink" href="#custom-content-negotiation">Custom content negotiation</a></h1>
<p>It's unlikely that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme override <code>BaseContentNegotiation</code>.</p>
<p>REST framework's content negotiation classes handle selection of both the appropriate parser for the request, and the appropriate renderer for the response, so you should implement both the <code>.select_parser(request, parsers)</code> and <code>.select_renderer(request, renderers, format_suffix)</code> methods.</p>

View File

@ -652,9 +652,10 @@
<p>&mdash; <a href="https://docs.djangoproject.com/en/stable/ref/forms/api/#django.forms.Form.cleaned_data">Django documentation</a></p>
</blockquote>
<p>Serializer fields handle converting between primitive values and internal datatypes. They also deal with validating input values, as well as retrieving and setting the values from their parent objects.</p>
<hr />
<p><strong>Note:</strong> The serializer fields are declared in <code>fields.py</code>, but by convention you should import them using <code>from rest_framework import serializers</code> and refer to fields as <code>serializers.&lt;FieldName&gt;</code>.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The serializer fields are declared in <code>fields.py</code>, but by convention you should import them using <code>from rest_framework import serializers</code> and refer to fields as <code>serializers.&lt;FieldName&gt;</code>.</p>
</div>
<h2 id="core-arguments"><a class="toclink" href="#core-arguments">Core arguments</a></h2>
<p>Each serializer field class constructor takes at least these arguments. Some Field classes take additional, field-specific arguments, but the following should always be accepted:</p>
<h3 id="read_only"><a class="toclink" href="#read_only"><code>read_only</code></a></h3>
@ -1030,9 +1031,10 @@ Django's regular <a href="https://docs.djangoproject.com/en/stable/ref/settings/
</code></pre>
<p>The <code>HiddenField</code> class is usually only needed if you have some validation that needs to run based on some pre-provided field values, but you do not want to expose all of those fields to the end user.</p>
<p>For further examples on <code>HiddenField</code> see the <a href="../validators/">validators</a> documentation.</p>
<hr />
<p><strong>Note:</strong> <code>HiddenField()</code> does not appear in <code>partial=True</code> serializer (when making <code>PATCH</code> request).</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code>HiddenField()</code> does not appear in <code>partial=True</code> serializer (when making <code>PATCH</code> request).</p>
</div>
<h2 id="modelfield"><a class="toclink" href="#modelfield">ModelField</a></h2>
<p>A generic field that can be tied to any arbitrary model field. The <code>ModelField</code> class delegates the task of serialization/deserialization to its associated model field. This field can be used to create serializer fields for custom model fields, without having to create a new custom serializer field.</p>
<p>This field is used by <code>ModelSerializer</code> to correspond to custom model field classes.</p>

View File

@ -623,9 +623,10 @@ class UserList(generics.ListCreateAPIView):
user = self.request.user
return user.accounts.all()
</code></pre>
<hr />
<p><strong>Note:</strong> If the <code>serializer_class</code> used in the generic view spans orm relations, leading to an n+1 problem, you could optimize your queryset in this method using <code>select_related</code> and <code>prefetch_related</code>. To get more information about n+1 problem and use cases of the mentioned methods refer to related section in <a href="https://docs.djangoproject.com/en/stable/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
<hr />
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>If the <code>serializer_class</code> used in the generic view spans ORM relations, leading to an N+1 problem, you could optimize your queryset in this method using <code>select_related</code> and <code>prefetch_related</code>. To get more information about N+1 problem and use cases of the mentioned methods refer to related section in <a href="https://docs.djangoproject.com/en/stable/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
</div>
<h3 id="avoiding-n1-queries"><a class="toclink" href="#avoiding-n1-queries">Avoiding N+1 Queries</a></h3>
<p>When listing objects (e.g. using <code>ListAPIView</code> or <code>ModelViewSet</code>), serializers may trigger an N+1 query pattern if related objects are accessed individually for each item.</p>
<p>To prevent this, optimize the queryset in <code>get_queryset()</code> or by setting the <code>queryset</code> class attribute using <a href="https://docs.djangoproject.com/en/stable/ref/models/querysets/#select-related"><code>select_related()</code></a> and <a href="https://docs.djangoproject.com/en/stable/ref/models/querysets/#prefetch-related"><code>prefetch_related()</code></a>, depending on the type of relationship.</p>

View File

@ -522,11 +522,12 @@ sending more complex data than simple forms</p>
<p>REST framework includes a number of built-in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.</p>
<h2 id="how-the-parser-is-determined"><a class="toclink" href="#how-the-parser-is-determined">How the parser is determined</a></h2>
<p>The set of valid parsers for a view is always defined as a list of classes. When <code>request.data</code> is accessed, REST framework will examine the <code>Content-Type</code> header on the incoming request, and determine which parser to use to parse the request content.</p>
<hr />
<p><strong>Note</strong>: When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p>
<p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you wanted.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p>
<p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you want.</p>
<p>As an example, if you are sending <code>json</code> encoded data using jQuery with the <a href="https://api.jquery.com/jQuery.ajax/">.ajax() method</a>, you should make sure to include the <code>contentType: 'application/json'</code> setting.</p>
<hr />
</div>
<h2 id="setting-the-parsers"><a class="toclink" href="#setting-the-parsers">Setting the parsers</a></h2>
<p>The default set of parsers may be set globally, using the <code>DEFAULT_PARSER_CLASSES</code> setting. For example, the following settings would allow only requests with <code>JSON</code> content, instead of the default of JSON or form data.</p>
<pre><code>REST_FRAMEWORK = {

View File

@ -579,15 +579,16 @@ or if you override the <code>get_object</code> method on a generic view, then yo
self.check_object_permissions(self.request, obj)
return obj
</code></pre>
<hr />
<p><strong>Note</strong>: With the exception of <code>DjangoObjectPermissions</code>, the provided
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>With the exception of <code>DjangoObjectPermissions</code>, the provided
permission classes in <code>rest_framework.permissions</code> <strong>do not</strong> implement the
methods necessary to check object permissions.</p>
<p>If you wish to use the provided permission classes in order to check object
permissions, <strong>you must</strong> subclass them and implement the
<code>has_object_permission()</code> method described in the <a href="#custom-permissions"><em>Custom
permissions</em></a> section (below).</p>
<hr />
</div>
<h4 id="limitations-of-object-level-permissions"><a class="toclink" href="#limitations-of-object-level-permissions">Limitations of object level permissions</a></h4>
<p>For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.</p>
<p>Often when you're using object level permissions you'll also want to <a href="../filtering/">filter the queryset</a> appropriately, to ensure that users only have visibility onto instances that they are permitted to view.</p>
@ -633,7 +634,10 @@ def example_view(request, format=None):
}
return Response(content)
</code></pre>
<p><strong>Note:</strong> when you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the <strong>settings.py</strong> file.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the <code>settings.py</code> file.</p>
</div>
<p>Provided they inherit from <code>rest_framework.permissions.BasePermission</code>, permissions can be composed using standard Python bitwise operators. For example, <code>IsAuthenticatedOrReadOnly</code> could be written:</p>
<pre><code>from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
@ -644,7 +648,7 @@ class ReadOnly(BasePermission):
return request.method in SAFE_METHODS
class ExampleView(APIView):
permission_classes = [IsAuthenticated|ReadOnly]
permission_classes = [IsAuthenticated | ReadOnly]
def get(self, request, format=None):
content = {
@ -652,8 +656,10 @@ class ExampleView(APIView):
}
return Response(content)
</code></pre>
<p><strong>Note:</strong> it supports &amp; (and), | (or) and ~ (not).</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Composition of permissions supports <code>&amp;</code> (and), <code>|</code> (or) and <code>~</code> (not) operators.</p>
</div>
<h1 id="api-reference"><a class="toclink" href="#api-reference">API Reference</a></h1>
<h2 id="allowany"><a class="toclink" href="#allowany">AllowAny</a></h2>
<p>The <code>AllowAny</code> permission class will allow unrestricted access, <strong>regardless of if the request was authenticated or unauthenticated</strong>.</p>
@ -688,9 +694,10 @@ class ExampleView(APIView):
</ul>
<p>Note that <code>DjangoObjectPermissions</code> <strong>does not</strong> require the <code>django-guardian</code> package, and should support other object-level backends equally well.</p>
<p>As with <code>DjangoModelPermissions</code> you can use custom model permissions by overriding <code>DjangoObjectPermissions</code> and setting the <code>.perms_map</code> property. Refer to the source code for details.</p>
<hr />
<p><strong>Note</strong>: If you need object level <code>view</code> permissions for <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the <code>DjangoObjectPermissionsFilter</code> class provided by the <a href="https://github.com/rpkilby/django-rest-framework-guardian"><code>djangorestframework-guardian</code> package</a>. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you need object level <code>view</code> permissions for <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the <code>DjangoObjectPermissionsFilter</code> class provided by the <a href="https://github.com/rpkilby/django-rest-framework-guardian"><code>djangorestframework-guardian</code> package</a>. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.</p>
</div>
<h1 id="custom-permissions"><a class="toclink" href="#custom-permissions">Custom permissions</a></h1>
<p>To implement a custom permission, override <code>BasePermission</code> and implement either, or both, of the following methods:</p>
<ul>
@ -704,9 +711,10 @@ class ExampleView(APIView):
else:
# Check permissions for write request
</code></pre>
<hr />
<p><strong>Note</strong>: The instance-level <code>has_object_permission</code> method will only be called if the view-level <code>has_permission</code> checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call <code>.check_object_permissions(request, obj)</code>. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising <code>PermissionDenied</code> on failure.)</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The instance-level <code>has_object_permission</code> method will only be called if the view-level <code>has_permission</code> checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call <code>.check_object_permissions(request, obj)</code>. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising <code>PermissionDenied</code> on failure.)</p>
</div>
<p>Custom permissions will raise a <code>PermissionDenied</code> exception if the test fails. To change the error message associated with the exception, implement a <code>message</code> attribute directly on your custom permission. Otherwise the <code>default_detail</code> attribute from <code>PermissionDenied</code> will be used. Similarly, to change the code identifier associated with the exception, implement a <code>code</code> attribute directly on your custom permission - otherwise the <code>default_code</code> attribute from <code>PermissionDenied</code> will be used.</p>
<pre><code>from rest_framework import permissions

View File

@ -552,11 +552,13 @@
<p>&mdash; <a href="http://users.ece.utexas.edu/~adnan/pike.html">Rob Pike</a></p>
</blockquote>
<p>Relational fields are used to represent model relationships. They can be applied to <code>ForeignKey</code>, <code>ManyToManyField</code> and <code>OneToOneField</code> relationships, as well as to reverse relationships, and custom relationships such as <code>GenericForeignKey</code>.</p>
<hr />
<p><strong>Note:</strong> The relational fields are declared in <code>relations.py</code>, but by convention you should import them from the <code>serializers</code> module, using <code>from rest_framework import serializers</code> and refer to fields as <code>serializers.&lt;FieldName&gt;</code>.</p>
<hr />
<hr />
<p><strong>Note:</strong> REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of <code>select_related</code> and <code>prefetch_related</code> since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The relational fields are declared in <code>relations.py</code>, but by convention you should import them from the <code>serializers</code> module, using <code>from rest_framework import serializers</code> and refer to fields as <code>serializers.&lt;FieldName&gt;</code>.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of <code>select_related</code> and <code>prefetch_related</code> since it would be too much magic. A serializer with a field spanning an ORM relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer.</p>
<p>For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:</p>
<pre><code>class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
@ -579,7 +581,7 @@ print(AlbumSerializer(qs, many=True).data)
print(AlbumSerializer(qs, many=True).data)
</code></pre>
<p>would solve the issue.</p>
<hr />
</div>
<h4 id="inspecting-relationships"><a class="toclink" href="#inspecting-relationships">Inspecting relationships.</a></h4>
<p>When using the <code>ModelSerializer</code> class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style.</p>
<p>To do so, open the Django shell, using <code>python manage.py shell</code>, then import the serializer class, instantiate it, and print the object representation…</p>
@ -694,11 +696,12 @@ class Track(models.Model):
}
</code></pre>
<p>By default this field is read-write, although you can change this behavior using the <code>read_only</code> flag.</p>
<hr />
<p><strong>Note</strong>: This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the <code>lookup_field</code> and <code>lookup_url_kwarg</code> arguments.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the <code>lookup_field</code> and <code>lookup_url_kwarg</code> arguments.</p>
<p>This is suitable for URLs that contain a single primary key or slug argument as part of the URL.</p>
<p>If you require more complex hyperlinked representation you'll need to customize the field, as described in the <a href="#custom-hyperlinked-fields">custom hyperlinked fields</a> section, below.</p>
<hr />
</div>
<p><strong>Arguments</strong>:</p>
<ul>
<li><code>view_name</code> - The view name that should be used as the target of the relationship. If you're using <a href="https://www.django-rest-framework.org/api-guide/routers#defaultrouter">the standard router classes</a> this will be a string with the format <code>&lt;modelname&gt;-detail</code>. <strong>required</strong>.</li>

View File

@ -651,11 +651,12 @@ def user_count_view(request, format=None):
<p>Renders data to HTML, using Django's standard template rendering.
Unlike other renderers, the data passed to the <code>Response</code> does not need to be serialized. Also, unlike other renderers, you may want to include a <code>template_name</code> argument when creating the <code>Response</code>.</p>
<p>The TemplateHTMLRenderer will create a <code>RequestContext</code>, using the <code>response.data</code> as the context dict, and determine a template name to use to render the context.</p>
<hr />
<p><strong>Note:</strong> When used with a view that makes use of a serializer the <code>Response</code> sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the <code>TemplateHTMLRenderer</code> to render it. For example:</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When used with a view that makes use of a serializer the <code>Response</code> sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the <code>TemplateHTMLRenderer</code> to render it. For example:</p>
<pre><code>response.data = {'results': response.data}
</code></pre>
<hr />
</div>
<p>The template name is determined by (in order of preference):</p>
<ol>
<li>An explicit <code>template_name</code> argument passed to the response.</li>
@ -714,13 +715,17 @@ def simple_html_view(request):
<p><img alt="The AdminRender view" src="../../img/admin.png" /></p>
<p>This renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.</p>
<p>Note that views that have nested or list serializers for their input won't work well with the <code>AdminRenderer</code>, as the HTML forms are unable to properly support them.</p>
<p><strong>Note</strong>: The <code>AdminRenderer</code> is only able to include links to detail pages when a properly configured <code>URL_FIELD_NAME</code> (<code>url</code> by default) attribute is present in the data. For <code>HyperlinkedModelSerializer</code> this will be the case, but for <code>ModelSerializer</code> or plain <code>Serializer</code> classes you'll need to make sure to include the field explicitly. For example here we use models <code>get_absolute_url</code> method:</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code>AdminRenderer</code> is only able to include links to detail pages when a properly configured <code>URL_FIELD_NAME</code> (<code>url</code> by default) attribute is present in the data. For <code>HyperlinkedModelSerializer</code> this will be the case, but for <code>ModelSerializer</code> or plain <code>Serializer</code> classes you'll need to make sure to include the field explicitly. </p>
<p>For example here we use models <code>get_absolute_url</code> method:</p>
<pre><code>class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = Account
</code></pre>
</div>
<p><strong>.media_type</strong>: <code>text/html</code></p>
<p><strong>.format</strong>: <code>'admin'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>
@ -847,8 +852,10 @@ In this case you can underspecify the media types it should respond to, by using
<li>Render the HTTP status code and text, for example "404 Not Found".</li>
</ul>
<p>Templates will render with a <code>RequestContext</code> which includes the <code>status_code</code> and <code>details</code> keys.</p>
<p><strong>Note</strong>: If <code>DEBUG=True</code>, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If <code>DEBUG=True</code>, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.</p>
</div>
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
<p>The following third party packages are also available.</p>
<h2 id="yaml"><a class="toclink" href="#yaml">YAML</a></h2>

View File

@ -535,10 +535,11 @@
<h2 id="parsers"><a class="toclink" href="#parsers">.parsers</a></h2>
<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Parser</code> instances, based on the <code>parser_classes</code> set on the view or based on the <code>DEFAULT_PARSER_CLASSES</code> setting.</p>
<p>You won't typically need to access this property.</p>
<hr />
<p><strong>Note:</strong> If a client sends malformed content, then accessing <code>request.data</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If a client sends malformed content, then accessing <code>request.data</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p>
<p>If a client sends a request with a content-type that cannot be parsed then a <code>UnsupportedMediaType</code> exception will be raised, which by default will be caught and return a <code>415 Unsupported Media Type</code> response.</p>
<hr />
</div>
<h1 id="content-negotiation"><a class="toclink" href="#content-negotiation">Content negotiation</a></h1>
<p>The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behavior such as selecting a different serialization schemes for different media types.</p>
<h2 id="accepted_renderer"><a class="toclink" href="#accepted_renderer">.accepted_renderer</a></h2>
@ -564,9 +565,10 @@
<h2 id="authenticators"><a class="toclink" href="#authenticators">.authenticators</a></h2>
<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Authentication</code> instances, based on the <code>authentication_classes</code> set on the view or based on the <code>DEFAULT_AUTHENTICATORS</code> setting.</p>
<p>You won't typically need to access this property.</p>
<hr />
<p><strong>Note:</strong> You may see a <code>WrappedAttributeError</code> raised when calling the <code>.user</code> or <code>.auth</code> properties. These errors originate from an authenticator as a standard <code>AttributeError</code>, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the <code>AttributeError</code> originates from the authenticator and will instead assume that the request object does not have a <code>.user</code> or <code>.auth</code> property. The authenticator will need to be fixed.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You may see a <code>WrappedAttributeError</code> raised when calling the <code>.user</code> or <code>.auth</code> properties. These errors originate from an authenticator as a standard <code>AttributeError</code>, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the <code>AttributeError</code> originates from the authenticator and will instead assume that the request object does not have a <code>.user</code> or <code>.auth</code> property. The authenticator will need to be fixed.</p>
</div>
<h1 id="browser-enhancements"><a class="toclink" href="#browser-enhancements">Browser enhancements</a></h1>
<p>REST framework supports a few browser enhancements such as browser-based <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> forms.</p>
<h2 id="method"><a class="toclink" href="#method">.method</a></h2>

View File

@ -524,13 +524,14 @@ urlpatterns = router.urls
<li>URL pattern: <code>^accounts/$</code> Name: <code>'account-list'</code></li>
<li>URL pattern: <code>^accounts/{pk}/$</code> Name: <code>'account-detail'</code></li>
</ul>
<hr />
<p><strong>Note</strong>: The <code>basename</code> argument is used to specify the initial part of the view name pattern. In the example above, that's the <code>user</code> or <code>account</code> part.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code>basename</code> argument is used to specify the initial part of the view name pattern. In the example above, that's the <code>user</code> or <code>account</code> part.</p>
<p>Typically you won't <em>need</em> to specify the <code>basename</code> argument, but if you have a viewset where you've defined a custom <code>get_queryset</code> method, then the viewset may not have a <code>.queryset</code> attribute set. If you try to register that viewset you'll see an error like this:</p>
<pre><code>'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
</code></pre>
<p>This means you'll need to explicitly set the <code>basename</code> argument when registering the viewset, as it could not be automatically determined from the model name.</p>
<hr />
</div>
<h3 id="using-include-with-routers"><a class="toclink" href="#using-include-with-routers">Using <code>include</code> with routers</a></h3>
<p>The <code>.urls</code> attribute on a router instance is simply a standard list of URL patterns. There are a number of different styles for how you can include these URLs.</p>
<p>For example, you can append <code>router.urls</code> to a list of existing views...</p>
@ -563,13 +564,14 @@ urlpatterns += router.urls
]
</code></pre>
<p>See Django's <a href="https://docs.djangoproject.com/en/stable/topics/http/urls/#url-namespaces">URL namespaces docs</a> and the <a href="https://docs.djangoproject.com/en/stable/ref/urls/#include"><code>include</code> API reference</a> for more details.</p>
<hr />
<p><strong>Note</strong>: If using namespacing with hyperlinked serializers you'll also need to ensure that any <code>view_name</code> parameters
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If using namespacing with hyperlinked serializers you'll also need to ensure that any <code>view_name</code> parameters
on the serializers correctly reflect the namespace. In the examples above you'd need to include a parameter such as
<code>view_name='app_name:user-detail'</code> for serializer fields hyperlinked to the user detail view.</p>
<p>The automatic <code>view_name</code> generation uses a pattern like <code>%(model_name)-detail</code>. Unless your models names actually clash
you may be better off <strong>not</strong> namespacing your Django REST Framework views when using hyperlinked serializers.</p>
<hr />
</div>
<h3 id="routing-for-extra-actions"><a class="toclink" href="#routing-for-extra-actions">Routing for extra actions</a></h3>
<p>A viewset may <a href="../viewsets/#marking-extra-actions-for-routing">mark extra actions for routing</a> by decorating a method with the <code>@action</code> decorator. These extra actions will be included in the generated routes. For example, given the <code>set_password</code> method on the <code>UserViewSet</code> class:</p>
<pre><code>from myapp.permissions import IsAdminOrIsSelf

View File

@ -650,13 +650,14 @@ operation = auto_schema.get_operation(...)
</code></pre>
<p>In compiling the schema, <code>SchemaGenerator</code> calls <code>get_components()</code> and
<code>get_operation()</code> for each view, allowed method, and path.</p>
<hr />
<p><strong>Note</strong>: The automatic introspection of components, and many operation
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The automatic introspection of components, and many operation
parameters relies on the relevant attributes and methods of
<code>GenericAPIView</code>: <code>get_serializer()</code>, <code>pagination_class</code>, <code>filter_backends</code>,
etc. For basic <code>APIView</code> subclasses, default introspection is essentially limited to
the URL kwarg path parameters for this reason.</p>
<hr />
</div>
<p><code>AutoSchema</code> encapsulates the view introspection needed for schema generation.
Because of this all the schema generation logic is kept in a single place,
rather than being spread around the already extensive view, serializer and

View File

@ -816,9 +816,10 @@ class BlogPostSerializer(serializers.Serializer):
raise serializers.ValidationError("Blog post is not about Django")
return value
</code></pre>
<hr />
<p><strong>Note:</strong> If your <code>&lt;field_name&gt;</code> is declared on your serializer with the parameter <code>required=False</code> then this validation step will not take place if the field is not included.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If your <code>&lt;field_name&gt;</code> is declared on your serializer with the parameter <code>required=False</code> then this validation step will not take place if the field is not included.</p>
</div>
<h4 id="object-level-validation"><a class="toclink" href="#object-level-validation">Object-level validation</a></h4>
<p>To do any other validation that requires access to multiple fields, add a method called <code>.validate()</code> to your <code>Serializer</code> subclass. This method takes a single argument, which is a dictionary of field values. It should raise a <code>serializers.ValidationError</code> if necessary, or just return the validated values. For example:</p>
<pre><code>from rest_framework import serializers
@ -1090,14 +1091,15 @@ AccountSerializer():
read_only_fields = ['account_name']
</code></pre>
<p>Model fields which have <code>editable=False</code> set, and <code>AutoField</code> fields will be set to read-only by default, and do not need to be added to the <code>read_only_fields</code> option.</p>
<hr />
<p><strong>Note</strong>: There is a special-case where a read-only field is part of a <code>unique_together</code> constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>There is a special-case where a read-only field is part of a <code>unique_together</code> constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.</p>
<p>The right way to deal with this is to specify the field explicitly on the serializer, providing both the <code>read_only=True</code> and <code>default=…</code> keyword arguments.</p>
<p>One example of this is a read-only relation to the currently authenticated <code>User</code> which is <code>unique_together</code> with another identifier. In this case you would declare the user field like so:</p>
<pre><code>user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
</code></pre>
<p>Please review the <a href="/api-guide/validators/">Validators Documentation</a> for details on the <a href="/api-guide/validators/#uniquetogethervalidator">UniqueTogetherValidator</a> and <a href="/api-guide/validators/#currentuserdefault">CurrentUserDefault</a> classes.</p>
<hr />
</div>
<h2 id="additional-keyword-arguments"><a class="toclink" href="#additional-keyword-arguments">Additional keyword arguments</a></h2>
<p>There is also a shortcut allowing you to specify arbitrary additional keyword arguments on fields, using the <code>extra_kwargs</code> option. As in the case of <code>read_only_fields</code>, this means you do not need to explicitly declare the field on the serializer.</p>
<p>This option is a dictionary, mapping field names to a dictionary of keyword arguments. For example:</p>

View File

@ -620,10 +620,13 @@ response = view(request)
request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user, token=user.auth_token)
</code></pre>
<hr />
<p><strong>Note</strong>: <code>force_authenticate</code> directly sets <code>request.user</code> to the in-memory <code>user</code> instance. If you are reusing the same <code>user</code> instance across multiple tests that update the saved <code>user</code> state, you may need to call <a href="https://docs.djangoproject.com/en/stable/ref/models/instances/#django.db.models.Model.refresh_from_db"><code>refresh_from_db()</code></a> between tests.</p>
<hr />
<p><strong>Note</strong>: When using <code>APIRequestFactory</code>, the object that is returned is Django's standard <code>HttpRequest</code>, and not REST framework's <code>Request</code> object, which is only generated once the view is called.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code>force_authenticate</code> directly sets <code>request.user</code> to the in-memory <code>user</code> instance. If you are reusing the same <code>user</code> instance across multiple tests that update the saved <code>user</code> state, you may need to call <a href="https://docs.djangoproject.com/en/stable/ref/models/instances/#django.db.models.Model.refresh_from_db"><code>refresh_from_db()</code></a> between tests.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When using <code>APIRequestFactory</code>, the object that is returned is Django's standard <code>HttpRequest</code>, and not REST framework's <code>Request</code> object, which is only generated once the view is called.</p>
<p>This means that setting attributes directly on the request object may not always have the effect you expect. For example, setting <code>.token</code> directly will have no effect, and setting <code>.user</code> directly will only work if session authentication is being used.</p>
<pre><code># Request will only authenticate if `SessionAuthentication` is in use.
request = factory.get('/accounts/django-superstars/')
@ -643,14 +646,15 @@ request = factory.post('/', {'example': 'test'})
drf_request = DummyView().initialize_request(request)
assert drf_request.data.get('example') == 'test'
</code></pre>
<hr />
</div>
<h2 id="forcing-csrf-validation"><a class="toclink" href="#forcing-csrf-validation">Forcing CSRF validation</a></h2>
<p>By default, requests created with <code>APIRequestFactory</code> will not have CSRF validation applied when passed to a REST framework view. If you need to explicitly turn CSRF validation on, you can do so by setting the <code>enforce_csrf_checks</code> flag when instantiating the factory.</p>
<pre><code>factory = APIRequestFactory(enforce_csrf_checks=True)
</code></pre>
<hr />
<p><strong>Note</strong>: It's worth noting that Django's standard <code>RequestFactory</code> doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>It's worth noting that Django's standard <code>RequestFactory</code> doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.</p>
</div>
<h1 id="apiclient"><a class="toclink" href="#apiclient">APIClient</a></h1>
<p>Extends <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client">Django's existing <code>Client</code> class</a>.</p>
<h2 id="making-requests"><a class="toclink" href="#making-requests">Making requests</a></h2>

View File

@ -589,9 +589,10 @@ class ExampleSerializer(serializers.Serializer):
)
]
</code></pre>
<hr />
<p><strong>Note</strong>: The <code>UniqueTogetherValidator</code> class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code>UniqueTogetherValidator</code> class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
</div>
<h2 id="uniquefordatevalidator"><a class="toclink" href="#uniquefordatevalidator">UniqueForDateValidator</a></h2>
<h2 id="uniqueformonthvalidator"><a class="toclink" href="#uniqueformonthvalidator">UniqueForMonthValidator</a></h2>
<h2 id="uniqueforyearvalidator"><a class="toclink" href="#uniqueforyearvalidator">UniqueForYearValidator</a></h2>
@ -631,16 +632,21 @@ class ExampleSerializer(serializers.Serializer):
<p>If you want the date field to be entirely hidden from the user, then use <code>HiddenField</code>. This field type does not accept user input, but instead always returns its default value to the <code>validated_data</code> in the serializer.</p>
<pre><code>published = serializers.HiddenField(default=timezone.now)
</code></pre>
<hr />
<p><strong>Note</strong>: The <code>UniqueFor&lt;Range&gt;Validator</code> classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
<hr />
<hr />
<p><strong>Note:</strong> <code>HiddenField()</code> does not appear in <code>partial=True</code> serializer (when making <code>PATCH</code> request). </p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code>UniqueFor&lt;Range&gt;Validator</code> classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code>HiddenField()</code> does not appear in <code>partial=True</code> serializer (when making <code>PATCH</code> request). </p>
</div>
<h1 id="advanced-field-defaults"><a class="toclink" href="#advanced-field-defaults">Advanced field defaults</a></h1>
<p>Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that <em>is</em> available as input to the validator.
For this purposes use <code>HiddenField</code>. This field will be present in <code>validated_data</code> but <em>will not</em> be used in the serializer output representation.</p>
<p><strong>Note:</strong> Using a <code>read_only=True</code> field is excluded from writable fields so it won't use a <code>default=…</code> argument. Look <a href="https://www.django-rest-framework.org/community/3.8-announcement/#altered-the-behavior-of-read_only-plus-default-on-field">3.8 announcement</a>.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Using a <code>read_only=True</code> field is excluded from writable fields so it won't use a <code>default=…</code> argument. Look <a href="https://www.django-rest-framework.org/community/3.8-announcement/#altered-the-behavior-of-read_only-plus-default-on-field">3.8 announcement</a>.</p>
</div>
<p>REST framework includes a couple of defaults that may be useful in this context.</p>
<h4 id="currentuserdefault"><a class="toclink" href="#currentuserdefault">CurrentUserDefault</a></h4>
<p>A default class that can be used to represent the current user. In order to use this, the 'request' must have been provided as part of the context dictionary when instantiating the serializer.</p>

View File

@ -513,9 +513,10 @@ class ListUsers(APIView):
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
</code></pre>
<hr />
<p><strong>Note</strong>: The full methods, attributes on, and relations between Django REST Framework's <code>APIView</code>, <code>GenericAPIView</code>, various <code>Mixins</code>, and <code>Viewsets</code> can be initially complex. In addition to the documentation here, the <a href="http://www.cdrf.co">Classy Django REST Framework</a> resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The full methods, attributes on, and relations between Django REST Framework's <code>APIView</code>, <code>GenericAPIView</code>, various <code>Mixins</code>, and <code>Viewsets</code> can be initially complex. In addition to the documentation here, the <a href="http://www.cdrf.co">Classy Django REST Framework</a> resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views.</p>
</div>
<h2 id="api-policy-attributes"><a class="toclink" href="#api-policy-attributes">API policy attributes</a></h2>
<p>The following attributes control the pluggable aspects of API views.</p>
<h3 id="renderer_classes"><a class="toclink" href="#renderer_classes">.renderer_classes</a></h3>

View File

@ -602,7 +602,10 @@ urlpatterns = router.urls
permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes]
</code></pre>
<p><strong>Note</strong>: the <code>action</code> attribute is not available in the <code>get_parsers</code>, <code>get_authenticators</code> and <code>get_content_negotiator</code> methods, as it is set <em>after</em> they are called in the framework lifecycle. If you override one of these methods and try to access the <code>action</code> attribute in them, you will get an <code>AttributeError</code> error.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code>action</code> attribute is not available in the <code>get_parsers</code>, <code>get_authenticators</code> and <code>get_content_negotiator</code> methods, as it is set <em>after</em> they are called in the framework lifecycle. If you override one of these methods and try to access the <code>action</code> attribute in them, you will get an <code>AttributeError</code> error.</p>
</div>
<h2 id="marking-extra-actions-for-routing"><a class="toclink" href="#marking-extra-actions-for-routing">Marking extra actions for routing</a></h2>
<p>If you have ad-hoc methods that should be routable, you can mark them as such with the <code>@action</code> decorator. Like regular actions, extra actions may be intended for either a single object, or an entire collection. To indicate this, set the <code>detail</code> argument to <code>True</code> or <code>False</code>. The router will configure its URL patterns accordingly. e.g., the <code>DefaultRouter</code> will configure detail actions to contain <code>pk</code> in their URL patterns.</p>
<p>A more complete example of extra actions:</p>

View File

@ -548,8 +548,9 @@ pip install -r requirements.txt
# Run the tests
./runtests.py
</code></pre>
<hr />
<p><strong>Note:</strong> if your tests require access to the database, do not forget to inherit from <code>django.test.TestCase</code> or use the <code>@pytest.mark.django_db()</code> decorator.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>If your tests require access to the database, do not forget to inherit from <code>django.test.TestCase</code> or use the <code>@pytest.mark.django_db()</code> decorator.</p>
<p>For example, with TestCase:</p>
<pre><code>from django.test import TestCase
@ -568,7 +569,7 @@ class MyDatabaseTest:
pass
</code></pre>
<p>You can reuse existing models defined in <code>tests/models.py</code> for your tests.</p>
<hr />
</div>
<h3 id="test-options"><a class="toclink" href="#test-options">Test options</a></h3>
<p>Run using a more concise output style.</p>
<pre><code>./runtests.py -q
@ -585,7 +586,10 @@ class MyDatabaseTest:
<p>Shorter form to run the tests for a given test method.</p>
<pre><code>./runtests.py test_this_method
</code></pre>
<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
</div>
<h3 id="running-against-multiple-environments"><a class="toclink" href="#running-against-multiple-environments">Running against multiple environments</a></h3>
<p>You can also use the excellent <a href="https://tox.readthedocs.io/en/latest/">tox</a> testing tool to run the tests against all supported versions of Python and Django. Install <code>tox</code> globally, and then simply run:</p>
<pre><code>tox
@ -643,13 +647,11 @@ More text...
</code></pre>
<p>Linking in this style means you'll be able to click the hyperlink in your Markdown editor to open the referenced document. When the documentation is built, these links will be converted into regular links to HTML pages.</p>
<h5 id="3-notes"><a class="toclink" href="#3-notes">3. Notes</a></h5>
<p>If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:</p>
<pre><code>---
**Note:** A useful documentation note.
---
<p>If you want to draw attention to a note or warning, use an <a href="https://python-markdown.github.io/extensions/admonition/">admonition</a>, like so:</p>
<pre><code>!!! note
A useful documentation note.
</code></pre>
<p>The documentation theme styles <code>info</code>, <code>warning</code>, <code>tip</code> and <code>danger</code> admonition types, but more could be added if the need arise.</p>
</div> <!--/span-->

View File

@ -452,6 +452,12 @@ ul.sponsor {
margin: 0 -.6rem 1em;
padding: 0.4rem 0.6rem;
}
.admonition.tip {
border: .075rem solid #1e8d21;
}
.admonition.tip .admonition-title {
background: #1e8d211a;
}
.admonition.warning {
border: .075rem solid #ff9844;
}

File diff suppressed because one or more lines are too long

View File

@ -2,347 +2,347 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.django-rest-framework.org/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/authentication/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/caching/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/content-negotiation/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/exceptions/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/fields/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/filtering/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/format-suffixes/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/generic-views/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/metadata/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/pagination/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/parsers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/permissions/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/relations/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/renderers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/requests/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/responses/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/reverse/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/routers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/schemas/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/serializers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/settings/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/status-codes/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/testing/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/throttling/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/validators/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/versioning/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/views/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/api-guide/viewsets/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.0-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.1-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.10-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.11-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.12-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.13-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.14-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.15-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.16-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.2-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.3-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.4-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.5-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.6-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.7-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.8-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/3.9-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/contributing/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/jobs/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/kickstarter-announcement/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/mozilla-grant/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/project-management/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/release-notes/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/third-party-packages/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/community/tutorials-and-resources/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/ajax-csrf-cors/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/browsable-api/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/browser-enhancements/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/documenting-your-api/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/html-and-forms/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/internationalization/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/rest-hypermedia-hateoas/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/topics/writable-nested-serializers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/1-serialization/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/2-requests-and-responses/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/3-class-based-views/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>https://www.django-rest-framework.org/tutorial/quickstart/</loc>
<lastmod>2025-12-09</lastmod>
<lastmod>2025-12-12</lastmod>
<changefreq>daily</changefreq>
</url>
</urlset>

Binary file not shown.

View File

@ -476,9 +476,10 @@
<h2 id="introduction"><a class="toclink" href="#introduction">Introduction</a></h2>
<p>This tutorial will cover creating a simple pastebin code highlighting Web API. Along the way it will introduce the various components that make up REST framework, and give you a comprehensive understanding of how everything fits together.</p>
<p>The tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the <a href="../quickstart/">quickstart</a> documentation instead.</p>
<hr />
<p><strong>Note</strong>: The code for this tutorial is available in the <a href="https://github.com/encode/rest-framework-tutorial">encode/rest-framework-tutorial</a> repository on GitHub. Feel free to clone the repository and see the code in action.</p>
<hr />
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The code for this tutorial is available in the <a href="https://github.com/encode/rest-framework-tutorial">encode/rest-framework-tutorial</a> repository on GitHub. Feel free to clone the repository and see the code in action.</p>
</div>
<h2 id="setting-up-a-new-environment"><a class="toclink" href="#setting-up-a-new-environment">Setting up a new environment</a></h2>
<p>Before we do anything else we'll create a new virtual environment, using <a href="https://docs.python.org/3/library/venv.html">venv</a>. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.</p>
<pre><code class="language-bash">python3 -m venv env
@ -489,7 +490,10 @@ source env/bin/activate
pip install djangorestframework
pip install pygments # We'll be using this for the code highlighting
</code></pre>
<p><strong>Note:</strong> To exit the virtual environment at any time, just type <code>deactivate</code>. For more information see the <a href="https://docs.python.org/3/library/venv.html">venv documentation</a>.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>To exit the virtual environment at any time, just type <code>deactivate</code>. For more information see the <a href="https://docs.python.org/3/library/venv.html">venv documentation</a>.</p>
</div>
<h2 id="getting-started"><a class="toclink" href="#getting-started">Getting started</a></h2>
<p>Okay, we're ready to get coding.
To get started, let's create a new project to work with.</p>

View File

@ -561,7 +561,10 @@ path(&quot;users/&lt;int:pk&gt;/&quot;, views.UserDetail.as_view()),
<p>Now that snippets are associated with the user that created them, let's update our <code>SnippetSerializer</code> to reflect that. Add the following field to the serializer definition in <code>serializers.py</code>:</p>
<pre><code class="language-python">owner = serializers.ReadOnlyField(source=&quot;owner.username&quot;)
</code></pre>
<p><strong>Note</strong>: Make sure you also add <code>'owner',</code> to the list of fields in the inner <code>Meta</code> class.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Make sure you also add <code>'owner',</code> to the list of fields in the inner <code>Meta</code> class.</p>
</div>
<p>This field is doing something quite interesting. The <code>source</code> argument controls which attribute is used to populate a field, and can point at any attribute on the serialized instance. It can also take the dotted notation shown above, in which case it will traverse the given attributes, in a similar way as it is used with Django's template language.</p>
<p>The field we've added is the untyped <code>ReadOnlyField</code> class, in contrast to the other typed fields, such as <code>CharField</code>, <code>BooleanField</code> etc... The untyped <code>ReadOnlyField</code> is always read-only, and will be used for serialized representations, but will not be used for updating model instances when they are deserialized. We could have also used <code>CharField(read_only=True)</code> here.</p>
<h2 id="adding-required-permissions-to-views"><a class="toclink" href="#adding-required-permissions-to-views">Adding required permissions to views</a></h2>

View File

@ -550,16 +550,16 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
</code></pre>
<p>Notice that we've also added a new <code>'highlight'</code> field. This field is of the same type as the <code>url</code> field, except that it points to the <code>'snippet-highlight'</code> url pattern, instead of the <code>'snippet-detail'</code> url pattern.</p>
<p>Because we've included format suffixed URLs such as <code>'.json'</code>, we also need to indicate on the <code>highlight</code> field that any format suffixed hyperlinks it returns should use the <code>'.html'</code> suffix.</p>
<hr />
<p><strong>Note:</strong></p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When you are manually instantiating these serializers inside your views (e.g., in <code>SnippetDetail</code> or <code>SnippetList</code>), you <strong>must</strong> pass <code>context={'request': request}</code> so the serializer knows how to build absolute URLs. For example, instead of:</p>
<pre><code class="language-python">serializer = SnippetSerializer(snippet)
<pre><code>serializer = SnippetSerializer(snippet)
</code></pre>
<p>You must write:</p>
<pre><code class="language-python">serializer = SnippetSerializer(snippet, context={&quot;request&quot;: request})
<pre><code>serializer = SnippetSerializer(snippet, context={"request": request})
</code></pre>
<p>If your view is a subclass of <code>GenericAPIView</code>, you may use the <code>get_serializer_context()</code> as a convenience method.</p>
<hr />
</div>
<h2 id="making-sure-our-url-patterns-are-named"><a class="toclink" href="#making-sure-our-url-patterns-are-named">Making sure our URL patterns are named</a></h2>
<p>If we're going to have a hyperlinked API, we need to make sure we name our URL patterns. Let's take a look at which URL patterns we need to name.</p>
<ul>