Deployed 0b2c03be with MkDocs version: 1.1.2

This commit is contained in:
Tom Christie 2023-11-29 14:16:17 +00:00
parent c8d45f9272
commit 5796b1ae95
78 changed files with 461 additions and 4706 deletions

View File

@ -238,10 +238,6 @@
<a href="/topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="/topics/api-clients/">API Clients</a>
</li>
<li >
<a href="/topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -684,7 +680,7 @@ for user in User.objects.all():
Token.objects.get_or_create(user=user)
</code></pre>
<h4 id="by-exposing-an-api-endpoint"><a class="toclink" href="#by-exposing-an-api-endpoint">By exposing an api endpoint</a></h4>
<p>When using <code>TokenAuthentication</code>, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behaviour. To use it, add the <code>obtain_auth_token</code> view to your URLconf:</p>
<p>When using <code>TokenAuthentication</code>, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the <code>obtain_auth_token</code> view to your URLconf:</p>
<pre><code>from rest_framework.authtoken import views
urlpatterns += [
path('api-token-auth/', views.obtain_auth_token)
@ -695,7 +691,7 @@ urlpatterns += [
<pre><code>{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }
</code></pre>
<p>Note that the default <code>obtain_auth_token</code> view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings.</p>
<p>By default, there are no permissions or throttling applied to the <code>obtain_auth_token</code> view. If you do wish to apply to throttle you'll need to override the view class,
<p>By default, there are no permissions or throttling applied to the <code>obtain_auth_token</code> view. If you do wish to apply throttling you'll need to override the view class,
and include them using the <code>throttle_classes</code> attribute.</p>
<p>If you need a customized version of the <code>obtain_auth_token</code> view, you can do so by subclassing the <code>ObtainAuthToken</code> view class, and using that in your url conf instead.</p>
<p>For example, you may return additional user information beyond the <code>token</code> value:</p>
@ -723,7 +719,7 @@ class CustomAuthToken(ObtainAuthToken):
]
</code></pre>
<h4 id="with-django-admin"><a class="toclink" href="#with-django-admin">With Django admin</a></h4>
<p>It is also possible to create Tokens manually through the admin interface. In case you are using a large user base, we recommend that you monkey patch the <code>TokenAdmin</code> class customize it to your needs, more specifically by declaring the <code>user</code> field as <code>raw_field</code>.</p>
<p>It is also possible to create Tokens manually through the admin interface. In case you are using a large user base, we recommend that you monkey patch the <code>TokenAdmin</code> class to customize it to your needs, more specifically by declaring the <code>user</code> field as <code>raw_field</code>.</p>
<p><code>your_app/admin.py</code>:</p>
<pre><code>from rest_framework.authtoken.admin import TokenAdmin
@ -747,22 +743,22 @@ TokenAdmin.raw_id_fields = ['user']
<li><code>request.auth</code> will be <code>None</code>.</li>
</ul>
<p>Unauthenticated responses that are denied permission will result in an <code>HTTP 403 Forbidden</code> response.</p>
<p>If you're using an AJAX-style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as <code>PUT</code>, <code>PATCH</code>, <code>POST</code> or <code>DELETE</code> requests. See the <a href="https://docs.djangoproject.com/en/stable/ref/csrf/#ajax">Django CSRF documentation</a> for more details.</p>
<p>If you're using an AJAX-style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as <code>PUT</code>, <code>PATCH</code>, <code>POST</code> or <code>DELETE</code> requests. See the <a href="https://docs.djangoproject.com/en/stable/howto/csrf/#using-csrf-protection-with-ajax">Django CSRF documentation</a> for more details.</p>
<p><strong>Warning</strong>: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.</p>
<p>CSRF validation in REST framework works slightly differently from standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.</p>
<p>CSRF validation in REST framework works slightly differently from standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behavior is not suitable for login views, which should always have CSRF validation applied.</p>
<h2 id="remoteuserauthentication"><a class="toclink" href="#remoteuserauthentication">RemoteUserAuthentication</a></h2>
<p>This authentication scheme allows you to delegate authentication to your web server, which sets the <code>REMOTE_USER</code>
environment variable.</p>
<p>To use it, you must have <code>django.contrib.auth.backends.RemoteUserBackend</code> (or a subclass) in your
<code>AUTHENTICATION_BACKENDS</code> setting. By default, <code>RemoteUserBackend</code> creates <code>User</code> objects for usernames that don't
already exist. To change this and other behaviour, consult the
already exist. To change this and other behavior, consult the
<a href="https://docs.djangoproject.com/en/stable/howto/auth-remote-user/">Django documentation</a>.</p>
<p>If successfully authenticated, <code>RemoteUserAuthentication</code> provides the following credentials:</p>
<ul>
<li><code>request.user</code> will be a Django <code>User</code> instance.</li>
<li><code>request.auth</code> will be <code>None</code>.</li>
</ul>
<p>Consult your web server's documentation for information about configuring an authentication method, e.g.:</p>
<p>Consult your web server's documentation for information about configuring an authentication method, for example:</p>
<ul>
<li><a href="https://httpd.apache.org/docs/2.4/howto/auth.html">Apache Authentication How-To</a></li>
<li><a href="https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/">NGINX (Restricting Access)</a></li>
@ -836,9 +832,9 @@ REST_FRAMEWORK = {
<h2 id="hawk-http-authentication"><a class="toclink" href="#hawk-http-authentication">Hawk HTTP Authentication</a></h2>
<p>The <a href="https://hawkrest.readthedocs.io/en/latest/">HawkREST</a> library builds on the <a href="https://mohawk.readthedocs.io/en/latest/">Mohawk</a> library to let you work with <a href="https://github.com/hueniverse/hawk">Hawk</a> signed requests and responses in your API. <a href="https://github.com/hueniverse/hawk">Hawk</a> lets two parties securely communicate with each other using messages signed by a shared key. It is based on <a href="https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05">HTTP MAC access authentication</a> (which was based on parts of <a href="https://oauth.net/core/1.0a/">OAuth 1.0</a>).</p>
<h2 id="http-signature-authentication"><a class="toclink" href="#http-signature-authentication">HTTP Signature Authentication</a></h2>
<p>HTTP Signature (currently a <a href="https://datatracker.ietf.org/doc/draft-cavage-http-signatures/">IETF draft</a>) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to <a href="https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html">Amazon's HTTP Signature scheme</a>, used by many of its services, it permits stateless, per-request authentication. <a href="https://github.com/etoccalino/">Elvio Toccalino</a> maintains the <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a> (outdated) package which provides an easy to use HTTP Signature Authentication mechanism. You can use the updated fork version of <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a>, which is <a href="https://github.com/ahknight/drf-httpsig">drf-httpsig</a>.</p>
<p>HTTP Signature (currently a <a href="https://datatracker.ietf.org/doc/draft-cavage-http-signatures/">IETF draft</a>) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to <a href="https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html">Amazon's HTTP Signature scheme</a>, used by many of its services, it permits stateless, per-request authentication. <a href="https://github.com/etoccalino/">Elvio Toccalino</a> maintains the <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a> (outdated) package which provides an easy-to-use HTTP Signature Authentication mechanism. You can use the updated fork version of <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a>, which is <a href="https://github.com/ahknight/drf-httpsig">drf-httpsig</a>.</p>
<h2 id="djoser"><a class="toclink" href="#djoser">Djoser</a></h2>
<p><a href="https://github.com/sunscrapers/djoser">Djoser</a> library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and uses token-based authentication. This is ready to use REST implementation of the Django authentication system.</p>
<p><a href="https://github.com/sunscrapers/djoser">Djoser</a> library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and uses token-based authentication. This is a ready to use REST implementation of the Django authentication system.</p>
<h2 id="django-rest-auth-dj-rest-auth"><a class="toclink" href="#django-rest-auth-dj-rest-auth">django-rest-auth / dj-rest-auth</a></h2>
<p>This library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.</p>
<p>There are currently two forks of this project.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -461,33 +457,33 @@ from rest_framework import viewsets
class UserViewSet(viewsets.ViewSet):
# With cookie: cache requested url for each user for 2 hours
@method_decorator(cache_page(60*60*2))
@method_decorator(cache_page(60 * 60 * 2))
@method_decorator(vary_on_cookie)
def list(self, request, format=None):
content = {
'user_feed': request.user.get_user_feed()
&quot;user_feed&quot;: request.user.get_user_feed(),
}
return Response(content)
class ProfileView(APIView):
# With auth: cache requested url for each user for 2 hours
@method_decorator(cache_page(60*60*2))
@method_decorator(vary_on_headers(&quot;Authorization&quot;,))
@method_decorator(cache_page(60 * 60 * 2))
@method_decorator(vary_on_headers(&quot;Authorization&quot;))
def get(self, request, format=None):
content = {
'user_feed': request.user.get_user_feed()
&quot;user_feed&quot;: request.user.get_user_feed(),
}
return Response(content)
class PostView(APIView):
# Cache page for the requested url
@method_decorator(cache_page(60*60*2))
@method_decorator(cache_page(60 * 60 * 2))
def get(self, request, format=None):
content = {
'title': 'Post title',
'body': 'Post content'
&quot;title&quot;: &quot;Post title&quot;,
&quot;body&quot;: &quot;Post content&quot;,
}
return Response(content)
</code></pre>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -595,7 +591,7 @@ def custom_exception_handler(exc, context):
<h2 id="apiexception"><a class="toclink" href="#apiexception">APIException</a></h2>
<p><strong>Signature:</strong> <code>APIException()</code></p>
<p>The <strong>base class</strong> for all exceptions raised inside an <code>APIView</code> class or <code>@api_view</code>.</p>
<p>To provide a custom exception, subclass <code>APIException</code> and set the <code>.status_code</code>, <code>.default_detail</code>, and <code>default_code</code> attributes on the class.</p>
<p>To provide a custom exception, subclass <code>APIException</code> and set the <code>.status_code</code>, <code>.default_detail</code>, and <code>.default_code</code> attributes on the class.</p>
<p>For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so:</p>
<pre><code>from rest_framework.exceptions import APIException
@ -649,7 +645,7 @@ dictionary of items:</p>
<p>By default this exception results in a response with the HTTP status code "403 Forbidden".</p>
<h2 id="notfound"><a class="toclink" href="#notfound">NotFound</a></h2>
<p><strong>Signature:</strong> <code>NotFound(detail=None, code=None)</code></p>
<p>Raised when a resource does not exists at the given URL. This exception is equivalent to the standard <code>Http404</code> Django exception.</p>
<p>Raised when a resource does not exist at the given URL. This exception is equivalent to the standard <code>Http404</code> Django exception.</p>
<p>By default this exception results in a response with the HTTP status code "404 Not Found".</p>
<h2 id="methodnotallowed"><a class="toclink" href="#methodnotallowed">MethodNotAllowed</a></h2>
<p><strong>Signature:</strong> <code>MethodNotAllowed(method, detail=None, code=None)</code></p>
@ -668,10 +664,9 @@ dictionary of items:</p>
<p>Raised when an incoming request fails the throttling checks.</p>
<p>By default this exception results in a response with the HTTP status code "429 Too Many Requests".</p>
<h2 id="validationerror"><a class="toclink" href="#validationerror">ValidationError</a></h2>
<p><strong>Signature:</strong> <code>ValidationError(detail, code=None)</code></p>
<p><strong>Signature:</strong> <code>ValidationError(detail=None, code=None)</code></p>
<p>The <code>ValidationError</code> exception is slightly different from the other <code>APIException</code> classes:</p>
<ul>
<li>The <code>detail</code> argument is mandatory, not optional.</li>
<li>The <code>detail</code> argument may be a list or dictionary of error details, and may also be a nested data structure. By using a dictionary, you can specify field-level errors while performing object-level validation in the <code>validate()</code> method of a serializer. For example. <code>raise serializers.ValidationError({'name': 'Please enter a valid name.'})</code></li>
<li>By convention you should import the serializers module and use a fully qualified <code>ValidationError</code> style, in order to differentiate it from Django's built-in validation error. For example. <code>raise serializers.ValidationError('This field must be an integer value.')</code></li>
</ul>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -666,7 +662,7 @@ Set to false if this field is not required to be present during deserialization.
<p>Setting this to <code>False</code> also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation.</p>
<p>Defaults to <code>True</code>. If you're using <a href="https://www.django-rest-framework.org/api-guide/serializers/#modelserializer">Model Serializer</a> default value will be <code>False</code> if you have specified <code>blank=True</code> or <code>default</code> or <code>null=True</code> at your field in your <code>Model</code>.</p>
<h3 id="default"><a class="toclink" href="#default"><code>default</code></a></h3>
<p>If set, this gives the default value that will be used for the field if no input value is supplied. If not set the default behaviour is to not populate the attribute at all.</p>
<p>If set, this gives the default value that will be used for the field if no input value is supplied. If not set the default behavior is to not populate the attribute at all.</p>
<p>The <code>default</code> is not applied during partial update operations. In the partial update case only fields that are provided in the incoming data will have a validated value returned.</p>
<p>May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a <code>requires_context = True</code> attribute, then the serializer field will be passed as an argument.</p>
<p>For example:</p>
@ -682,17 +678,21 @@ Set to false if this field is not required to be present during deserialization.
</code></pre>
<p>When serializing the instance, default will be used if the object attribute or dictionary key is not present in the instance.</p>
<p>Note that setting a <code>default</code> value implies that the field is not required. Including both the <code>default</code> and <code>required</code> keyword arguments is invalid and will raise an error.</p>
<p>Notes regarding default value propagation from model to serializer:</p>
<p>All the default values from model will pass as default to the serializer and the options method.</p>
<p>If the default is callable then it will be propagated to &amp; evaluated every time in the serializer but not in options method.</p>
<p>If the value for given field is not given then default value will be present in the serializer and available in serializer's methods. Specified validation on given field will be evaluated on default value as that field will be present in the serializer.</p>
<h3 id="allow_null"><a class="toclink" href="#allow_null"><code>allow_null</code></a></h3>
<p>Normally an error will be raised if <code>None</code> is passed to a serializer field. Set this keyword argument to <code>True</code> if <code>None</code> should be considered a valid value.</p>
<p>Note that, without an explicit <code>default</code>, setting this argument to <code>True</code> will imply a <code>default</code> value of <code>null</code> for serialization output, but does not imply a default for input deserialization.</p>
<p>Defaults to <code>False</code></p>
<h3 id="source"><a class="toclink" href="#source"><code>source</code></a></h3>
<p>The name of the attribute that will be used to populate the field. May be a method that only takes a <code>self</code> argument, such as <code>URLField(source='get_absolute_url')</code>, or may use dotted notation to traverse attributes, such as <code>EmailField(source='user.email')</code>. </p>
<p>The name of the attribute that will be used to populate the field. May be a method that only takes a <code>self</code> argument, such as <code>URLField(source='get_absolute_url')</code>, or may use dotted notation to traverse attributes, such as <code>EmailField(source='user.email')</code>.</p>
<p>When serializing fields with dotted notation, it may be necessary to provide a <code>default</code> value if any object is not present or is empty during attribute traversal. Beware of possible n+1 problems when using source attribute if you are accessing a relational orm model. For example:</p>
<pre><code>class CommentSerializer(serializers.Serializer):
email = serializers.EmailField(source="user.email")
</code></pre>
<p>would require user object to be fetched from database when it is not prefetched. If that is not wanted, be sure to be using <code>prefetch_related</code> and <code>select_related</code> methods appropriately. For more information about the methods refer to <a href="https://docs.djangoproject.com/en/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
<p>This case would require user object to be fetched from database when it is not prefetched. If that is not wanted, be sure to be using <code>prefetch_related</code> and <code>select_related</code> methods appropriately. For more information about the methods refer to <a href="https://docs.djangoproject.com/en/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
<p>The value <code>source='*'</code> has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation.</p>
<p>Defaults to the name of the field.</p>
<h3 id="validators"><a class="toclink" href="#validators"><code>validators</code></a></h3>
@ -736,7 +736,7 @@ Prior to Django 2.1 <code>models.BooleanField</code> fields were always <code>bl
since Django 2.1 default <code>serializers.BooleanField</code> instances will be generated
without the <code>required</code> kwarg (i.e. equivalent to <code>required=True</code>) whereas with
previous versions of Django, default <code>BooleanField</code> instances will be generated
with a <code>required=False</code> option. If you want to control this behaviour manually,
with a <code>required=False</code> option. If you want to control this behavior manually,
explicitly declare the <code>BooleanField</code> on the serializer class, or use the
<code>extra_kwargs</code> option to set the <code>required</code> flag.</p>
<p>Corresponds to <code>django.db.models.fields.BooleanField</code>.</p>
@ -803,7 +803,7 @@ explicitly declare the <code>BooleanField</code> on the serializer class, or use
<p>Corresponds to <code>django.forms.fields.IPAddressField</code> and <code>django.forms.fields.GenericIPAddressField</code>.</p>
<p><strong>Signature</strong>: <code>IPAddressField(protocol='both', unpack_ipv4=False, **options)</code></p>
<ul>
<li><code>protocol</code> Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case insensitive.</li>
<li><code>protocol</code> Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case-insensitive.</li>
<li><code>unpack_ipv4</code> Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'.</li>
</ul>
<hr />
@ -835,7 +835,8 @@ explicitly declare the <code>BooleanField</code> on the serializer class, or use
<li><code>max_value</code> Validate that the number provided is no greater than this value.</li>
<li><code>min_value</code> Validate that the number provided is no less than this value.</li>
<li><code>localize</code> Set to <code>True</code> to enable localization of input and output based on the current locale. This will also force <code>coerce_to_string</code> to <code>True</code>. Defaults to <code>False</code>. Note that data formatting is enabled if you have set <code>USE_L10N=True</code> in your settings file.</li>
<li><code>rounding</code> Sets the rounding mode used when quantising to the configured precision. Valid values are <a href="https://docs.python.org/3/library/decimal.html#rounding-modes"><code>decimal</code> module rounding modes</a>. Defaults to <code>None</code>.</li>
<li><code>rounding</code> Sets the rounding mode used when quantizing to the configured precision. Valid values are <a href="https://docs.python.org/3/library/decimal.html#rounding-modes"><code>decimal</code> module rounding modes</a>. Defaults to <code>None</code>.</li>
<li><code>normalize_output</code> Will normalize the decimal value when serialized. This will strip all trailing zeroes and change the value's precision to the minimum required precision to be able to represent the value without loosing data. Defaults to <code>False</code>.</li>
</ul>
<h4 id="example-usage"><a class="toclink" href="#example-usage">Example usage</a></h4>
<p>To validate numbers up to 999 with a resolution of 2 decimal places, you would use:</p>
@ -853,11 +854,11 @@ explicitly declare the <code>BooleanField</code> on the serializer class, or use
<ul>
<li><code>format</code> - A string representing the output format. If not specified, this defaults to the same value as the <code>DATETIME_FORMAT</code> settings key, which will be <code>'iso-8601'</code> unless set. Setting to a format string indicates that <code>to_representation</code> return values should be coerced to string output. Format strings are described below. Setting this value to <code>None</code> indicates that Python <code>datetime</code> objects should be returned by <code>to_representation</code>. In this case the datetime encoding will be determined by the renderer.</li>
<li><code>input_formats</code> - A list of strings representing the input formats which may be used to parse the date. If not specified, the <code>DATETIME_INPUT_FORMATS</code> setting will be used, which defaults to <code>['iso-8601']</code>.</li>
<li><code>default_timezone</code> - A <code>tzinfo</code> subclass (<code>zoneinfo</code> or <code>pytz</code>) prepresenting the timezone. If not specified and the <code>USE_TZ</code> setting is enabled, this defaults to the <a href="https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone">current timezone</a>. If <code>USE_TZ</code> is disabled, then datetime objects will be naive.</li>
<li><code>default_timezone</code> - A <code>tzinfo</code> subclass (<code>zoneinfo</code> or <code>pytz</code>) representing the timezone. If not specified and the <code>USE_TZ</code> setting is enabled, this defaults to the <a href="https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone">current timezone</a>. If <code>USE_TZ</code> is disabled, then datetime objects will be naive.</li>
</ul>
<h4 id="datetimefield-format-strings"><a class="toclink" href="#datetimefield-format-strings"><code>DateTimeField</code> format strings.</a></h4>
<p>Format strings may either be <a href="https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior">Python strftime formats</a> which explicitly specify the format, or the special string <code>'iso-8601'</code>, which indicates that <a href="https://www.w3.org/TR/NOTE-datetime">ISO 8601</a> style datetimes should be used. (eg <code>'2013-01-29T12:34:56.000000Z'</code>)</p>
<p>When a value of <code>None</code> is used for the format <code>datetime</code> objects will be returned by <code>to_representation</code> and the final output representation will determined by the renderer class.</p>
<p>When a value of <code>None</code> is used for the format <code>datetime</code> objects will be returned by <code>to_representation</code> and the final output representation will be determined by the renderer class.</p>
<h4 id="auto_now-and-auto_now_add-model-fields"><a class="toclink" href="#auto_now-and-auto_now_add-model-fields"><code>auto_now</code> and <code>auto_now_add</code> model fields.</a></h4>
<p>When using <code>ModelSerializer</code> or <code>HyperlinkedModelSerializer</code>, note that any model fields with <code>auto_now=True</code> or <code>auto_now_add=True</code> will use serializer fields that are <code>read_only=True</code> by default.</p>
<p>If you want to override this behavior, you'll need to declare the <code>DateTimeField</code> explicitly on the serializer. For example:</p>
@ -1014,6 +1015,9 @@ 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). This behavior might change in future, follow updates on <a href="https://github.com/encode/django-rest-framework/discussions/8259">github discussion</a>. </p>
<hr />
<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>
@ -1211,7 +1215,7 @@ class DataPointSerializer(serializers.ModelSerializer):
<p>Here the mapping between the target and source attribute pairs (<code>x</code> and
<code>x_coordinate</code>, <code>y</code> and <code>y_coordinate</code>) is handled in the <code>IntegerField</code>
declarations. It's our <code>NestedCoordinateSerializer</code> that takes <code>source='*'</code>.</p>
<p>Our new <code>DataPointSerializer</code> exhibits the same behaviour as the custom field
<p>Our new <code>DataPointSerializer</code> exhibits the same behavior as the custom field
approach.</p>
<p>Serializing:</p>
<pre><code>&gt;&gt;&gt; out_serializer = DataPointSerializer(instance)
@ -1256,7 +1260,7 @@ or overly complex.</p>
<h2 id="djangorestframework-recursive"><a class="toclink" href="#djangorestframework-recursive">djangorestframework-recursive</a></h2>
<p>the <a href="https://github.com/heywbj/django-rest-framework-recursive">djangorestframework-recursive</a> package provides a <code>RecursiveField</code> for serializing and deserializing recursive structures</p>
<h2 id="django-rest-framework-gis"><a class="toclink" href="#django-rest-framework-gis">django-rest-framework-gis</a></h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides geographic addons for django rest framework like a <code>GeometryField</code> field and a GeoJSON serializer.</p>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides geographic addons for django rest framework like a <code>GeometryField</code> field and a GeoJSON serializer.</p>
<h2 id="django-rest-framework-hstore"><a class="toclink" href="#django-rest-framework-hstore">django-rest-framework-hstore</a></h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreField</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -479,10 +475,6 @@
<a href="#customizing-the-interface">Customizing the interface</a>
</li>
<li>
<a href="#filtering-schemas">Filtering &amp; schemas</a>
</li>
<li class="main">
<a href="#third-party-packages">Third party packages</a>
@ -692,14 +684,44 @@ class UserListView(generics.ListAPIView):
<p>For <a href="https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#jsonfield">JSONField</a> and <a href="https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#hstorefield">HStoreField</a> fields you can filter based on nested values within the data structure using the same double-underscore notation:</p>
<pre><code>search_fields = ['data__breed', 'data__owner__other_pets__0__name']
</code></pre>
<p>By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.</p>
<p>The search behavior may be restricted by prepending various characters to the <code>search_fields</code>.</p>
<ul>
<li>'^' Starts-with search.</li>
<li>'=' Exact matches.</li>
<li>'@' Full-text search. (Currently only supported Django's <a href="https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/">PostgreSQL backend</a>.)</li>
<li>'$' Regex search.</li>
</ul>
<p>By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched. Searches may contain <em>quoted phrases</em> with spaces, each phrase is considered as a single search term.</p>
<p>The search behavior may be specified by prefixing field names in <code>search_fields</code> with one of the following characters (which is equivalent to adding <code>__&lt;lookup&gt;</code> to the field):</p>
<table>
<thead>
<tr>
<th>Prefix</th>
<th>Lookup</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>^</code></td>
<td><code>istartswith</code></td>
<td>Starts-with search.</td>
</tr>
<tr>
<td><code>=</code></td>
<td><code>iexact</code></td>
<td>Exact matches.</td>
</tr>
<tr>
<td><code>$</code></td>
<td><code>iregex</code></td>
<td>Regex search.</td>
</tr>
<tr>
<td><code>@</code></td>
<td><code>search</code></td>
<td>Full-text search (Currently only supported Django's <a href="https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/">PostgreSQL backend</a>).</td>
</tr>
<tr>
<td>None</td>
<td><code>icontains</code></td>
<td>Contains search (Default).</td>
</tr>
</tbody>
</table>
<p>For example:</p>
<pre><code>search_fields = ['=username', '=email']
</code></pre>
@ -718,7 +740,7 @@ class CustomSearchFilter(filters.SearchFilter):
<h2 id="orderingfilter"><a class="toclink" href="#orderingfilter">OrderingFilter</a></h2>
<p>The <code>OrderingFilter</code> class supports simple query parameter controlled ordering of results.</p>
<p><img alt="Ordering Filter" src="../../img/ordering-filter.png" /></p>
<p>By default, the query parameter is named <code>'ordering'</code>, but this may by overridden with the <code>ORDERING_PARAM</code> setting.</p>
<p>By default, the query parameter is named <code>'ordering'</code>, but this may be overridden with the <code>ORDERING_PARAM</code> setting.</p>
<p>For example, to order users by username:</p>
<pre><code>http://example.com/api/users?ordering=username
</code></pre>
@ -729,7 +751,7 @@ class CustomSearchFilter(filters.SearchFilter):
<pre><code>http://example.com/api/users?ordering=account,username
</code></pre>
<h3 id="specifying-which-fields-may-be-ordered-against"><a class="toclink" href="#specifying-which-fields-may-be-ordered-against">Specifying which fields may be ordered against</a></h3>
<p>It's recommended that you explicitly specify which fields the API should allowing in the ordering filter. You can do this by setting an <code>ordering_fields</code> attribute on the view, like so:</p>
<p>It's recommended that you explicitly specify which fields the API should allow in the ordering filter. You can do this by setting an <code>ordering_fields</code> attribute on the view, like so:</p>
<pre><code>class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
@ -775,11 +797,6 @@ class CustomSearchFilter(filters.SearchFilter):
<p>Generic filters may also present an interface in the browsable API. To do so you should implement a <code>to_html()</code> method which returns a rendered HTML representation of the filter. This method should have the following signature:</p>
<p><code>to_html(self, request, queryset, view)</code></p>
<p>The method should return a rendered HTML string.</p>
<h2 id="filtering-schemas"><a class="toclink" href="#filtering-schemas">Filtering &amp; schemas</a></h2>
<p>You can also make the filter controls available to the schema autogeneration
that REST framework provides, by implementing a <code>get_schema_fields()</code> method. This method should have the following signature:</p>
<p><code>get_schema_fields(self, view)</code></p>
<p>The method should return a list of <code>coreapi.Field</code> instances.</p>
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
<p>The following third party packages provide additional filter implementations.</p>
<h2 id="django-rest-framework-filters-package"><a class="toclink" href="#django-rest-framework-filters-package">Django REST framework filters package</a></h2>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -464,8 +460,8 @@ used all the time.</p>
<p>Arguments:</p>
<ul>
<li><strong>urlpatterns</strong>: Required. A URL pattern list.</li>
<li><strong>suffix_required</strong>: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to <code>False</code>, meaning that suffixes are optional by default.</li>
<li><strong>allowed</strong>: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used.</li>
<li><strong>suffix_required</strong>: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to <code>False</code>, meaning that suffixes are optional by default.</li>
<li><strong>allowed</strong>: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used.</li>
</ul>
<p>Example:</p>
<pre><code>from rest_framework.urlpatterns import format_suffix_patterns

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -624,7 +620,7 @@ class UserList(generics.ListCreateAPIView):
return user.accounts.all()
</code></pre>
<hr />
<p><strong>Note:</strong> If the serializer_class 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/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
<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/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related">django documentation</a>.</p>
<hr />
<h4 id="get_objectself"><a class="toclink" href="#get_objectself"><code>get_object(self)</code></a></h4>
<p>Returns an object instance that should be used for detail views. Defaults to using the <code>lookup_field</code> parameter to filter the base queryset.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -457,10 +453,6 @@
<a href="#using-your-custom-pagination-class">Using your custom pagination class</a>
</li>
<li>
<a href="#pagination-schemas">Pagination &amp; schemas</a>
</li>
<li class="main">
<a href="#html-pagination-controls">HTML pagination controls</a>
@ -681,7 +673,7 @@ class StandardResultsSetPagination(PageNumberPagination):
</ul>
<p>Note that the <code>paginate_queryset</code> method may set state on the pagination instance, that may later be used by the <code>get_paginated_response</code> method.</p>
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
<p>Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:</p>
<p>Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:</p>
<pre><code>class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
return Response({
@ -693,7 +685,7 @@ class StandardResultsSetPagination(PageNumberPagination):
'results': data
})
</code></pre>
<p>We'd then need to setup the custom class in our configuration:</p>
<p>We'd then need to set up the custom class in our configuration:</p>
<pre><code>REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
'PAGE_SIZE': 100
@ -709,12 +701,7 @@ class StandardResultsSetPagination(PageNumberPagination):
</code></pre>
<p>API responses for list endpoints will now include a <code>Link</code> header, instead of including the pagination links as part of the body of the response, for example:</p>
<p><img alt="Link Header" src="../../img/link-header-pagination.png" /></p>
<p><em>A custom pagination style, using the 'Link' header'</em></p>
<h2 id="pagination-schemas"><a class="toclink" href="#pagination-schemas">Pagination &amp; schemas</a></h2>
<p>You can also make the pagination controls available to the schema autogeneration
that REST framework provides, by implementing a <code>get_schema_fields()</code> method. This method should have the following signature:</p>
<p><code>get_schema_fields(self, view)</code></p>
<p>The method should return a list of <code>coreapi.Field</code> instances.</p>
<p><em>A custom pagination style, using the 'Link' header</em></p>
<hr />
<h1 id="html-pagination-controls"><a class="toclink" href="#html-pagination-controls">HTML pagination controls</a></h1>
<p>By default using the pagination classes will cause HTML pagination controls to be displayed in the browsable API. There are two built-in display styles. The <code>PageNumberPagination</code> and <code>LimitOffsetPagination</code> classes display a list of page numbers with previous and next controls. The <code>CursorPagination</code> class displays a simpler style that only displays a previous and next control.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -519,9 +515,9 @@ structured formats for sending data than form-encoded, since they're
sending more complex data than simple forms</p>
<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
</blockquote>
<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>
<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>
<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>
@ -573,7 +569,7 @@ def example_view(request, format=None):
<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
<p><strong>.media_type</strong>: <code>application/x-www-form-urlencoded</code></p>
<h2 id="multipartparser"><a class="toclink" href="#multipartparser">MultiPartParser</a></h2>
<p>Parses multipart HTML form content, which supports file uploads. Both <code>request.data</code> will be populated with a <code>QueryDict</code>.</p>
<p>Parses multipart HTML form content, which supports file uploads. <code>request.data</code> and <code>request.FILES</code> will be populated with a <code>QueryDict</code> and <code>MultiValueDict</code> respectively.</p>
<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
<p><strong>.media_type</strong>: <code>multipart/form-data</code></p>
<h2 id="fileuploadparser"><a class="toclink" href="#fileuploadparser">FileUploadParser</a></h2>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -505,6 +501,10 @@
<a href="#django-rest-framework-roles">Django Rest Framework Roles</a>
</li>
<li>
<a href="#rest-framework-roles">Rest Framework Roles</a>
</li>
<li>
<a href="#django-rest-framework-api-key">Django REST Framework API Key</a>
</li>
@ -657,16 +657,17 @@ class ExampleView(APIView):
<p>The <code>IsAdminUser</code> permission class will deny permission to any user, unless <code>user.is_staff</code> is <code>True</code> in which case permission will be allowed.</p>
<p>This permission is suitable if you want your API to only be accessible to a subset of trusted administrators.</p>
<h2 id="isauthenticatedorreadonly"><a class="toclink" href="#isauthenticatedorreadonly">IsAuthenticatedOrReadOnly</a></h2>
<p>The <code>IsAuthenticatedOrReadOnly</code> will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the "safe" methods; <code>GET</code>, <code>HEAD</code> or <code>OPTIONS</code>.</p>
<p>The <code>IsAuthenticatedOrReadOnly</code> will allow authenticated users to perform any request. Requests for unauthenticated users will only be permitted if the request method is one of the "safe" methods; <code>GET</code>, <code>HEAD</code> or <code>OPTIONS</code>.</p>
<p>This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.</p>
<h2 id="djangomodelpermissions"><a class="toclink" href="#djangomodelpermissions">DjangoModelPermissions</a></h2>
<p>This permission class ties into Django's standard <code>django.contrib.auth</code> <a href="https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions">model permissions</a>. This permission must only be applied to views that have a <code>.queryset</code> property or <code>get_queryset()</code> method. Authorization will only be granted if the user <em>is authenticated</em> and has the <em>relevant model permissions</em> assigned. The appropriate model is determined by checking <code>get_queryset().model</code> or <code>queryset.model</code>.</p>
<ul>
<li><code>GET</code> requests require the user to have the <code>view</code> or <code>change</code> permission on the model</li>
<li><code>POST</code> requests require the user to have the <code>add</code> permission on the model.</li>
<li><code>PUT</code> and <code>PATCH</code> requests require the user to have the <code>change</code> permission on the model.</li>
<li><code>DELETE</code> requests require the user to have the <code>delete</code> permission on the model.</li>
</ul>
<p>The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a <code>view</code> model permission for <code>GET</code> requests.</p>
<p>The default behaviour can also be overridden to support custom model permissions.</p>
<p>To use custom model permissions, override <code>DjangoModelPermissions</code> and set the <code>.perms_map</code> property. Refer to the source code for details.</p>
<h2 id="djangomodelpermissionsoranonreadonly"><a class="toclink" href="#djangomodelpermissionsoranonreadonly">DjangoModelPermissionsOrAnonReadOnly</a></h2>
<p>Similar to <code>DjangoModelPermissions</code>, but also allows unauthenticated users to have read-only access to the API.</p>
@ -681,7 +682,7 @@ class ExampleView(APIView):
<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>
<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/johnthagen/django-rest-framework-guardian2"><code>djangorestframework-guardian2</code> package</a>. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.</p>
<hr />
<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>
@ -823,6 +824,8 @@ class BlocklistPermission(permissions.BasePermission):
<p>The <a href="https://github.com/FJNR-inc/dry-rest-permissions">DRY Rest Permissions</a> package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.</p>
<h2 id="django-rest-framework-roles"><a class="toclink" href="#django-rest-framework-roles">Django Rest Framework Roles</a></h2>
<p>The <a href="https://github.com/computer-lab/django-rest-framework-roles">Django Rest Framework Roles</a> package makes it easier to parameterize your API over multiple types of users.</p>
<h2 id="rest-framework-roles"><a class="toclink" href="#rest-framework-roles">Rest Framework Roles</a></h2>
<p>The <a href="https://github.com/Pithikos/rest-framework-roles">Rest Framework Roles</a> makes it super easy to protect views based on roles. Most importantly allows you to decouple accessibility logic from models and views in a clean human-readable way.</p>
<h2 id="django-rest-framework-api-key"><a class="toclink" href="#django-rest-framework-api-key">Django REST Framework API Key</a></h2>
<p>The <a href="https://florimondmanca.github.io/djangorestframework-api-key/">Django REST Framework API Key</a> package provides permissions classes, models and helpers to add API key authorization to your API. It can be used to authorize internal or third-party backends and services (i.e. <em>machines</em>) which do not have a user account. API keys are stored securely using Django's password hashing infrastructure, and they can be viewed, edited and revoked at anytime in the Django admin.</p>
<h2 id="django-rest-framework-role-filters"><a class="toclink" href="#django-rest-framework-role-filters">Django Rest Framework Role Filters</a></h2>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -745,7 +741,7 @@ class Track(models.Model):
<li><code>allow_null</code> - If set to <code>True</code>, the field will accept values of <code>None</code> or the empty string for nullable relationships. Defaults to <code>False</code>.</li>
</ul>
<h2 id="hyperlinkedidentityfield"><a class="toclink" href="#hyperlinkedidentityfield">HyperlinkedIdentityField</a></h2>
<p>This field can be applied as an identity relationship, such as the <code>'url'</code> field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:</p>
<p>This field can be applied as an identity relationship, such as the <code>'url'</code> field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:</p>
<pre><code>class AlbumSerializer(serializers.HyperlinkedModelSerializer):
track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')
@ -772,7 +768,7 @@ class Track(models.Model):
<h1 id="nested-relationships"><a class="toclink" href="#nested-relationships">Nested relationships</a></h1>
<p>As opposed to previously discussed <em>references</em> to another entity, the referred entity can instead also be embedded or <em>nested</em>
in the representation of the object that refers to it.
Such nested relationships can be expressed by using serializers as fields. </p>
Such nested relationships can be expressed by using serializers as fields.</p>
<p>If the field is used to represent a to-many relationship, you should add the <code>many=True</code> flag to the serializer field.</p>
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
<p>For example, the following serializer:</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -496,7 +492,7 @@
<li>
<a href="#varying-behaviour-by-media-type">Varying behaviour by media type</a>
<a href="#varying-behavior-by-media-type">Varying behavior by media type</a>
</li>
<li>
@ -652,7 +648,7 @@ def user_count_view(request, format=None):
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 TemplateHTMLRenderer to render it. For example:</p>
<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>
<pre><code>response.data = {'results': response.data}
</code></pre>
<hr />
@ -803,7 +799,7 @@ class PlainTextRenderer(renderers.BaseRenderer):
<li>Specify multiple types of HTML representation for API clients to use.</li>
<li>Underspecify a renderer's media type, such as using <code>media_type = 'image/*'</code>, and use the <code>Accept</code> header to vary the encoding of the response.</li>
</ul>
<h2 id="varying-behaviour-by-media-type"><a class="toclink" href="#varying-behaviour-by-media-type">Varying behaviour by media type</a></h2>
<h2 id="varying-behavior-by-media-type"><a class="toclink" href="#varying-behavior-by-media-type">Varying behavior by media type</a></h2>
<p>In some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access <code>request.accepted_renderer</code> to determine the negotiated renderer that will be used for the response.</p>
<p>For example:</p>
<pre><code>@api_view(['GET'])

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -540,7 +536,7 @@
<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 />
<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 behaviour such as selecting a different serialization schemes for different media types.</p>
<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>
<p>The renderer instance that was selected by the content negotiation stage.</p>
<h2 id="accepted_media_type"><a class="toclink" href="#accepted_media_type">.accepted_media_type</a></h2>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -463,7 +459,7 @@
<p>There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink its output for you, which makes browsing the API much easier.</p>
<h2 id="reverse"><a class="toclink" href="#reverse">reverse</a></h2>
<p><strong>Signature:</strong> <code>reverse(viewname, *args, **kwargs)</code></p>
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse"><code>django.urls.reverse</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse"><code>django.urls.reverse</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
<p>You should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
<pre><code>from rest_framework.reverse import reverse
from rest_framework.views import APIView
@ -480,7 +476,7 @@ class APIRootView(APIView):
</code></pre>
<h2 id="reverse_lazy"><a class="toclink" href="#reverse_lazy">reverse_lazy</a></h2>
<p><strong>Signature:</strong> <code>reverse_lazy(viewname, *args, **kwargs)</code></p>
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy"><code>django.urls.reverse_lazy</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse-lazy"><code>django.urls.reverse_lazy</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
<p>As with the <code>reverse</code> function, you should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
<pre><code>api_root = reverse_lazy('api-root', request=request)
</code></pre>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -626,10 +622,18 @@ This behavior can be modified by setting the <code>trailing_slash</code> argumen
<pre><code>router = SimpleRouter(trailing_slash=False)
</code></pre>
<p>Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.</p>
<p>The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the <code>lookup_value_regex</code> attribute on the viewset. For example, you can limit the lookup to valid UUIDs:</p>
<p>By default the URLs created by <code>SimpleRouter</code> use regular expressions. This behavior can be modified by setting the <code>use_regex_path</code> argument to <code>False</code> when instantiating the router, in this case <a href="https://docs.djangoproject.com/en/2.0/topics/http/urls/#path-converters">path converters</a> are used. For example:</p>
<pre><code>router = SimpleRouter(use_regex_path=False)
</code></pre>
<p><strong>Note</strong>: <code>use_regex_path=False</code> only works with Django 2.x or above, since this feature was introduced in 2.0.0. See <a href="https://docs.djangoproject.com/en/2.0/releases/2.0/#simplified-url-routing-syntax">release note</a></p>
<p>The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the <code>lookup_value_regex</code> attribute on the viewset or <code>lookup_value_converter</code> if using path converters. For example, you can limit the lookup to valid UUIDs:</p>
<pre><code>class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
class MyPathModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_uuid'
lookup_value_converter = 'uuid'
</code></pre>
<h2 id="defaultrouter"><a class="toclink" href="#defaultrouter">DefaultRouter</a></h2>
<p>This router is similar to <code>SimpleRouter</code> as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional <code>.json</code> style format suffixes.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -459,6 +455,18 @@
<p>A machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support.</p>
<p>&mdash; Heroku, <a href="https://blog.heroku.com/archives/2014/1/8/json_schema_for_heroku_platform_api">JSON Schema for the Heroku Platform API</a></p>
</blockquote>
<hr />
<p><strong>Deprecation notice:</strong></p>
<p>REST framework's built-in support for generating OpenAPI schemas is
<strong>deprecated</strong> in favor of 3rd party packages that can provide this
functionality instead. The built-in support will be moved into a separate
package and then subsequently retired over the next releases.</p>
<p>As a full-fledged replacement, we recommend the <a href="https://drf-spectacular.readthedocs.io/en/latest/readme.html">drf-spectacular</a> package.
It has extensive support for generating OpenAPI 3 schemas from
REST framework APIs, with both automatic and customisable options available.
For further information please refer to
<a href="../../topics/documenting-your-api/#drf-spectacular">Documenting your API</a>.</p>
<hr />
<p>API schemas are a useful tool that allow for a range of use cases, including
generating reference documentation, or driving dynamic client libraries that
can interact with your API.</p>
@ -511,11 +519,13 @@ urlpatterns = [
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
# * `title` and `description` parameters are passed to `SchemaGenerator`.
# * Provide view name for use with `reverse()`.
path('openapi', get_schema_view(
title=&quot;Your Project&quot;,
description=&quot;API for all things …&quot;,
version=&quot;1.0.0&quot;
), name='openapi-schema'),
path(
&quot;openapi&quot;,
get_schema_view(
title=&quot;Your Project&quot;, description=&quot;API for all things …&quot;, version=&quot;1.0.0&quot;
),
name=&quot;openapi-schema&quot;,
),
# ...
]
</code></pre>
@ -557,6 +567,9 @@ schema_view = get_schema_view(
patterns=schema_url_patterns,
)
</code></pre>
<ul>
<li><code>public</code>: May be used to specify if schema should bypass views permissions. Default to False</li>
</ul>
</li>
<li>
<p><code>generator_class</code>: May be used to specify a <code>SchemaGenerator</code> subclass to be
@ -650,11 +663,13 @@ be tempted to do something like this:</p>
&quot;&quot;&quot;
AutoSchema subclass using schema_extra_info on the view.
&quot;&quot;&quot;
...
class CustomView(APIView):
schema = CustomSchema()
schema_extra_info = ... some extra info ...
schema_extra_info = ... # some extra info
</code></pre>
<p>Here, the <code>AutoSchema</code> subclass goes looking for <code>schema_extra_info</code> on the
view. This is <em>OK</em> (it doesn't actually hurt) but it means you'll end up with
@ -665,10 +680,13 @@ out into the view:</p>
&quot;&quot;&quot;
AutoSchema subclass that knows how to use extra_info.
&quot;&quot;&quot;
...
class CustomSchema(BaseSchema):
extra_info = ... some extra info ...
extra_info = ... # some extra info
class CustomView(APIView):
schema = CustomSchema()
@ -685,18 +703,17 @@ option as an <code>__init__()</code> kwarg to your base <code>AutoSchema</code>
self.extra_info = kwargs.pop(&quot;extra_info&quot;)
super().__init__(**kwargs)
class CustomView(APIView):
schema = CustomSchema(
extra_info=... some extra info ...
)
schema = CustomSchema(extra_info=...) # some extra info
</code></pre>
<p>This saves you having to create a custom subclass per-view for a commonly used option.</p>
<p>Not all <code>AutoSchema</code> methods expose related <code>__init__()</code> kwargs, but those for
<p>Not all <code>AutoSchema</code> methods expose related <code>__init__()</code> kwargs, but those for
the more commonly needed options do.</p>
<h3 id="autoschema-methods"><a class="toclink" href="#autoschema-methods"><code>AutoSchema</code> methods</a></h3>
<h4 id="get_components"><a class="toclink" href="#get_components"><code>get_components()</code></a></h4>
<p>Generates the OpenAPI components that describe request and response bodies,
deriving their properties from the serializer.</p>
deriving their properties from the serializer.</p>
<p>Returns a dictionary mapping the component name to the generated
representation. By default this has just a single pair but you may override
<code>get_components()</code> to return multiple pairs if your view uses multiple

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -839,7 +835,7 @@ class EventSerializer(serializers.Serializer):
raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten])
score = serializers.IntegerField(validators=[multiple_of_ten])
...
</code></pre>
<p>Serializer classes can also include reusable validators that are applied to the complete set of field data. These validators are included by declaring them on an inner <code>Meta</code> class, like so:</p>
@ -1120,38 +1116,38 @@ AccountSerializer():
<h2 id="customizing-field-mappings"><a class="toclink" href="#customizing-field-mappings">Customizing field mappings</a></h2>
<p>The ModelSerializer class also exposes an API that you can override in order to alter how serializer fields are automatically determined when instantiating the serializer.</p>
<p>Normally if a <code>ModelSerializer</code> does not generate the fields you need by default then you should either add them to the class explicitly, or simply use a regular <code>Serializer</code> class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model.</p>
<h3 id="serializer_field_mapping"><a class="toclink" href="#serializer_field_mapping"><code>.serializer_field_mapping</code></a></h3>
<h3 id="serializer_field_mapping"><a class="toclink" href="#serializer_field_mapping"><code>serializer_field_mapping</code></a></h3>
<p>A mapping of Django model fields to REST framework serializer fields. You can override this mapping to alter the default serializer fields that should be used for each model field.</p>
<h3 id="serializer_related_field"><a class="toclink" href="#serializer_related_field"><code>.serializer_related_field</code></a></h3>
<h3 id="serializer_related_field"><a class="toclink" href="#serializer_related_field"><code>serializer_related_field</code></a></h3>
<p>This property should be the serializer field class, that is used for relational fields by default.</p>
<p>For <code>ModelSerializer</code> this defaults to <code>serializers.PrimaryKeyRelatedField</code>.</p>
<p>For <code>HyperlinkedModelSerializer</code> this defaults to <code>serializers.HyperlinkedRelatedField</code>.</p>
<h3 id="serializer_url_field"><a class="toclink" href="#serializer_url_field"><code>.serializer_url_field</code></a></h3>
<h3 id="serializer_url_field"><a class="toclink" href="#serializer_url_field"><code>serializer_url_field</code></a></h3>
<p>The serializer field class that should be used for any <code>url</code> field on the serializer.</p>
<p>Defaults to <code>serializers.HyperlinkedIdentityField</code></p>
<h3 id="serializer_choice_field"><a class="toclink" href="#serializer_choice_field"><code>.serializer_choice_field</code></a></h3>
<h3 id="serializer_choice_field"><a class="toclink" href="#serializer_choice_field"><code>serializer_choice_field</code></a></h3>
<p>The serializer field class that should be used for any choice fields on the serializer.</p>
<p>Defaults to <code>serializers.ChoiceField</code></p>
<h3 id="the-field_class-and-field_kwargs-api"><a class="toclink" href="#the-field_class-and-field_kwargs-api">The field_class and field_kwargs API</a></h3>
<p>The following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of <code>(field_class, field_kwargs)</code>.</p>
<h3 id="build_standard_fieldself-field_name-model_field"><a class="toclink" href="#build_standard_fieldself-field_name-model_field"><code>.build_standard_field(self, field_name, model_field)</code></a></h3>
<h3 id="build_standard_fieldself-field_name-model_field"><a class="toclink" href="#build_standard_fieldself-field_name-model_field"><code>build_standard_field(self, field_name, model_field)</code></a></h3>
<p>Called to generate a serializer field that maps to a standard model field.</p>
<p>The default implementation returns a serializer class based on the <code>serializer_field_mapping</code> attribute.</p>
<h3 id="build_relational_fieldself-field_name-relation_info"><a class="toclink" href="#build_relational_fieldself-field_name-relation_info"><code>.build_relational_field(self, field_name, relation_info)</code></a></h3>
<h3 id="build_relational_fieldself-field_name-relation_info"><a class="toclink" href="#build_relational_fieldself-field_name-relation_info"><code>build_relational_field(self, field_name, relation_info)</code></a></h3>
<p>Called to generate a serializer field that maps to a relational model field.</p>
<p>The default implementation returns a serializer class based on the <code>serializer_related_field</code> attribute.</p>
<p>The <code>relation_info</code> argument is a named tuple, that contains <code>model_field</code>, <code>related_model</code>, <code>to_many</code> and <code>has_through_model</code> properties.</p>
<h3 id="build_nested_fieldself-field_name-relation_info-nested_depth"><a class="toclink" href="#build_nested_fieldself-field_name-relation_info-nested_depth"><code>.build_nested_field(self, field_name, relation_info, nested_depth)</code></a></h3>
<h3 id="build_nested_fieldself-field_name-relation_info-nested_depth"><a class="toclink" href="#build_nested_fieldself-field_name-relation_info-nested_depth"><code>build_nested_field(self, field_name, relation_info, nested_depth)</code></a></h3>
<p>Called to generate a serializer field that maps to a relational model field, when the <code>depth</code> option has been set.</p>
<p>The default implementation dynamically creates a nested serializer class based on either <code>ModelSerializer</code> or <code>HyperlinkedModelSerializer</code>.</p>
<p>The <code>nested_depth</code> will be the value of the <code>depth</code> option, minus one.</p>
<p>The <code>relation_info</code> argument is a named tuple, that contains <code>model_field</code>, <code>related_model</code>, <code>to_many</code> and <code>has_through_model</code> properties.</p>
<h3 id="build_property_fieldself-field_name-model_class"><a class="toclink" href="#build_property_fieldself-field_name-model_class"><code>.build_property_field(self, field_name, model_class)</code></a></h3>
<h3 id="build_property_fieldself-field_name-model_class"><a class="toclink" href="#build_property_fieldself-field_name-model_class"><code>build_property_field(self, field_name, model_class)</code></a></h3>
<p>Called to generate a serializer field that maps to a property or zero-argument method on the model class.</p>
<p>The default implementation returns a <code>ReadOnlyField</code> class.</p>
<h3 id="build_url_fieldself-field_name-model_class"><a class="toclink" href="#build_url_fieldself-field_name-model_class"><code>.build_url_field(self, field_name, model_class)</code></a></h3>
<h3 id="build_url_fieldself-field_name-model_class"><a class="toclink" href="#build_url_fieldself-field_name-model_class"><code>build_url_field(self, field_name, model_class)</code></a></h3>
<p>Called to generate a serializer field for the serializer's own <code>url</code> field. The default implementation returns a <code>HyperlinkedIdentityField</code> class.</p>
<h3 id="build_unknown_fieldself-field_name-model_class"><a class="toclink" href="#build_unknown_fieldself-field_name-model_class"><code>.build_unknown_field(self, field_name, model_class)</code></a></h3>
<h3 id="build_unknown_fieldself-field_name-model_class"><a class="toclink" href="#build_unknown_fieldself-field_name-model_class"><code>build_unknown_field(self, field_name, model_class)</code></a></h3>
<p>Called when the field name did not map to any model field or model property.
The default implementation raises an error, although subclasses may customize this behavior.</p>
<hr />
@ -1222,9 +1218,9 @@ in the serializer context.</p>
<h3 id="allow_empty"><a class="toclink" href="#allow_empty"><code>allow_empty</code></a></h3>
<p>This is <code>True</code> by default, but can be set to <code>False</code> if you want to disallow empty lists as valid input.</p>
<h3 id="max_length"><a class="toclink" href="#max_length"><code>max_length</code></a></h3>
<p>This is <code>None</code> by default, but can be set to a positive integer if you want to validates that the list contains no more than this number of elements.</p>
<p>This is <code>None</code> by default, but can be set to a positive integer if you want to validate that the list contains no more than this number of elements.</p>
<h3 id="min_length"><a class="toclink" href="#min_length"><code>min_length</code></a></h3>
<p>This is <code>None</code> by default, but can be set to a positive integer if you want to validates that the list contains no fewer than this number of elements.</p>
<p>This is <code>None</code> by default, but can be set to a positive integer if you want to validate that the list contains no fewer than this number of elements.</p>
<h3 id="customizing-listserializer-behavior"><a class="toclink" href="#customizing-listserializer-behavior">Customizing <code>ListSerializer</code> behavior</a></h3>
<p>There <em>are</em> a few use cases when you might want to customize the <code>ListSerializer</code> behavior. For example:</p>
<ul>
@ -1444,7 +1440,7 @@ def all_high_scores(request):
<li>Improving serialization performance for a frequently accessed API endpoint that returns lots of data.</li>
</ul>
<p>The signatures for these methods are as follows:</p>
<h4 id="to_representationself-instance"><a class="toclink" href="#to_representationself-instance"><code>.to_representation(self, instance)</code></a></h4>
<h4 id="to_representationself-instance"><a class="toclink" href="#to_representationself-instance"><code>to_representation(self, instance)</code></a></h4>
<p>Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API.</p>
<p>May be overridden in order to modify the representation style. For example:</p>
<pre><code>def to_representation(self, instance):
@ -1453,7 +1449,7 @@ def all_high_scores(request):
ret['username'] = ret['username'].lower()
return ret
</code></pre>
<h4 id="to_internal_valueself-data"><a class="toclink" href="#to_internal_valueself-data"><code>.to_internal_value(self, data)</code></a></h4>
<h4 id="to_internal_valueself-data"><a class="toclink" href="#to_internal_valueself-data"><code>to_internal_value(self, data)</code></a></h4>
<p>Takes the unvalidated incoming data as input and should return the validated data that will be made available as <code>serializer.validated_data</code>. The return value will also be passed to the <code>.create()</code> or <code>.update()</code> methods if <code>.save()</code> is called on the serializer class.</p>
<p>If any of the validation fails, then the method should raise a <code>serializers.ValidationError(errors)</code>. The <code>errors</code> argument should be a dictionary mapping field names (or <code>settings.NON_FIELD_ERRORS_KEY</code>) to a list of error messages. If you don't need to alter deserialization behavior and instead want to provide object-level validation, it's recommended that you instead override the <a href="#object-level-validation"><code>.validate()</code></a> method.</p>
<p>The <code>data</code> argument passed to this method will normally be the value of <code>request.data</code>, so the datatype it provides will depend on the parser classes you have configured for your API.</p>
@ -1562,7 +1558,7 @@ blacklisted and child serializers can be optionally expanded.</p>
<h2 id="drf-writable-nested"><a class="toclink" href="#drf-writable-nested">DRF Writable Nested</a></h2>
<p>The <a href="https://github.com/beda-software/drf-writable-nested">drf-writable-nested</a> package provides writable nested model serializer which allows to create/update models with nested related data.</p>
<h2 id="drf-encrypt-content"><a class="toclink" href="#drf-encrypt-content">DRF Encrypt Content</a></h2>
<p>The <a href="https://github.com/oguzhancelikarslan/drf-encrypt-content">drf-encrypt-content</a> package helps you encrypt your data, serialized through ModelSerializer. It also contains some helper functions. Which helps you to encrypt your data. </p>
<p>The <a href="https://github.com/oguzhancelikarslan/drf-encrypt-content">drf-encrypt-content</a> package helps you encrypt your data, serialized through ModelSerializer. It also contains some helper functions. Which helps you to encrypt your data.</p>
</div> <!--/span-->

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -597,6 +593,9 @@ is disabled by default. See the pagination documentation for further guidance on
<h4 id="version_param"><a class="toclink" href="#version_param">VERSION_PARAM</a></h4>
<p>The string that should used for any versioning parameters, such as in the media type or URL query parameters.</p>
<p>Default: <code>'version'</code></p>
<h4 id="default_versioning_class"><a class="toclink" href="#default_versioning_class">DEFAULT_VERSIONING_CLASS</a></h4>
<p>The default versioning scheme to use.</p>
<p>Default: <code>None</code></p>
<hr />
<h2 id="authentication-settings"><a class="toclink" href="#authentication-settings">Authentication settings</a></h2>
<p><em>The following settings control the behavior of unauthenticated requests.</em></p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -492,6 +488,8 @@ and <a href="https://tools.ietf.org/html/rfc6585">RFC 6585</a>.</p>
<p>This class of status code indicates a provisional response. There are no 1xx status codes used in REST framework by default.</p>
<pre><code>HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
HTTP_102_PROCESSING
HTTP_103_EARLY_HINTS
</code></pre>
<h2 id="successful-2xx"><a class="toclink" href="#successful-2xx">Successful - 2xx</a></h2>
<p>This class of status code indicates that the client's request was successfully received, understood, and accepted.</p>
@ -538,9 +536,11 @@ HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_421_MISDIRECTED_REQUEST
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_425_TOO_EARLY
HTTP_426_UPGRADE_REQUIRED
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -520,7 +516,7 @@
<p>With <code>ModelForm</code> the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:</p>
<ul>
<li>It introduces a proper separation of concerns, making your code behavior more obvious.</li>
<li>It is easy to switch between using shortcut <code>ModelSerializer</code> classes and using explicit <code>Serializer</code> classes. Any validation behavior being used for <code>ModelSerializer</code> is simple to replicate.</li>
<li>It is easy to switch between using shortcut <code>ModelSerializer</code> classes and using explicit <code>Serializer</code> classes. Any validation behavior being used for <code>ModelSerializer</code> is simple to replicate.</li>
<li>Printing the <code>repr</code> of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance.</li>
</ul>
<p>When you're using <code>ModelSerializer</code> all of this is handled automatically for you. If you want to drop down to using <code>Serializer</code> classes instead, then you need to define the validation rules explicitly.</p>
@ -547,7 +543,7 @@ CustomerReportSerializer():
description = CharField(style={'type': 'textarea'})
</code></pre>
<p>The interesting bit here is the <code>reference</code> field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field.</p>
<p>Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below.</p>
<p>Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below. REST framework validators, like their Django counterparts, implement the <code>__eq__</code> method, allowing you to compare instances for equality.</p>
<hr />
<h2 id="uniquevalidator"><a class="toclink" href="#uniquevalidator">UniqueValidator</a></h2>
<p>This validator can be used to enforce the <code>unique=True</code> constraint on model fields.
@ -634,6 +630,9 @@ class ExampleSerializer(serializers.Serializer):
<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). This behavior might change in future, follow updates on <a href="https://github.com/encode/django-rest-framework/discussions/8259">github discussion</a>. </p>
<hr />
<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.</p>
<p>Two patterns that you may want to use for this sort of validation include:</p>
@ -665,7 +664,7 @@ by specifying an empty list for the serializer <code>Meta.validators</code> attr
<h2 id="optional-fields"><a class="toclink" href="#optional-fields">Optional fields</a></h2>
<p>By default "unique together" validation enforces that all fields be
<code>required=True</code>. In some cases, you might want to explicit apply
<code>required=False</code> to one of the fields, in which case the desired behaviour
<code>required=False</code> to one of the fields, in which case the desired behavior
of the validation is ambiguous.</p>
<p>In this case you will typically need to exclude the validator from the
serializer class, and instead write any validation logic explicitly, either
@ -732,13 +731,14 @@ to your <code>Serializer</code> subclass. This is documented in the
<h4 id="accessing-the-context"><a class="toclink" href="#accessing-the-context">Accessing the context</a></h4>
<p>In some advanced cases you might want a validator to be passed the serializer
field it is being used with as additional context. You can do so by setting
a <code>requires_context = True</code> attribute on the validator. The <code>__call__</code> method
a <code>requires_context = True</code> attribute on the validator class. The <code>__call__</code> method
will then be called with the <code>serializer_field</code>
or <code>serializer</code> as an additional argument.</p>
<pre><code>requires_context = True
<pre><code>class MultipleOf:
requires_context = True
def __call__(self, value, serializer_field):
...
def __call__(self, value, serializer_field):
...
</code></pre>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -573,7 +569,7 @@ def hello_world(request):
return Response({"message": "Hello, world!"})
</code></pre>
<p>This view will use the default renderers, parsers, authentication classes etc specified in the <a href="../settings/">settings</a>.</p>
<p>By default only <code>GET</code> methods will be accepted. Other methods will respond with "405 Method Not Allowed". To alter this behaviour, specify which methods the view allows, like so:</p>
<p>By default only <code>GET</code> methods will be accepted. Other methods will respond with "405 Method Not Allowed". To alter this behavior, specify which methods the view allows, like so:</p>
<pre><code>@api_view(['GET', 'POST'])
def hello_world(request):
if request.method == 'POST':

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -587,7 +583,7 @@ urlpatterns = router.urls
<li><code>name</code> - the display name for the viewset. This argument is mutually exclusive to <code>suffix</code>.</li>
<li><code>description</code> - the display description for the individual view of a viewset.</li>
</ul>
<p>You may inspect these attributes to adjust behaviour based on the current action. For example, you could restrict permissions to everything except the <code>list</code> action similar to this:</p>
<p>You may inspect these attributes to adjust behavior based on the current action. For example, you could restrict permissions to everything except the <code>list</code> action similar to this:</p>
<pre><code>def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
@ -643,6 +639,13 @@ class UserViewSet(viewsets.ModelViewSet):
def unset_password(self, request, pk=None):
...
</code></pre>
<p>Argument <code>methods</code> also supports HTTP methods defined as <a href="https://docs.python.org/3/library/http.html#http.HTTPMethod">HTTPMethod</a>. Example below is identical to the one above: </p>
<pre><code> from http import HTTPMethod
@action(detail=True, methods=[HTTPMethod.POST, HTTPMethod.DELETE])
def unset_password(self, request, pk=None):
...
</code></pre>
<p>The decorator allows you to override any viewset-level configuration such as <code>permission_classes</code>, <code>serializer_class</code>, <code>filter_backends</code>...:</p>
<pre><code> @action(detail=True, methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
@ -652,25 +655,26 @@ class UserViewSet(viewsets.ModelViewSet):
<p>To view all extra actions, call the <code>.get_extra_actions()</code> method.</p>
<h3 id="routing-additional-http-methods-for-extra-actions"><a class="toclink" href="#routing-additional-http-methods-for-extra-actions">Routing additional HTTP methods for extra actions</a></h3>
<p>Extra actions can map additional HTTP methods to separate <code>ViewSet</code> methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments.</p>
<pre><code class="language-python"> @action(detail=True, methods=['put'], name='Change Password')
def password(self, request, pk=None):
&quot;&quot;&quot;Update the user's password.&quot;&quot;&quot;
...
<pre><code class="language-python">@action(detail=True, methods=[&quot;put&quot;], name=&quot;Change Password&quot;)
def password(self, request, pk=None):
&quot;&quot;&quot;Update the user's password.&quot;&quot;&quot;
...
@password.mapping.delete
def delete_password(self, request, pk=None):
&quot;&quot;&quot;Delete the user's password.&quot;&quot;&quot;
...
@password.mapping.delete
def delete_password(self, request, pk=None):
&quot;&quot;&quot;Delete the user's password.&quot;&quot;&quot;
...
</code></pre>
<h2 id="reversing-action-urls"><a class="toclink" href="#reversing-action-urls">Reversing action URLs</a></h2>
<p>If you need to get the URL of an action, use the <code>.reverse_action()</code> method. This is a convenience wrapper for <code>reverse()</code>, automatically passing the view's <code>request</code> object and prepending the <code>url_name</code> with the <code>.basename</code> attribute.</p>
<p>Note that the <code>basename</code> is provided by the router during <code>ViewSet</code> registration. If you are not using a router, then you must provide the <code>basename</code> argument to the <code>.as_view()</code> method.</p>
<p>Using the example from the previous section:</p>
<pre><code class="language-python">&gt;&gt;&gt; view.reverse_action('set-password', args=['1'])
<pre><code class="language-pycon">&gt;&gt;&gt; view.reverse_action(&quot;set-password&quot;, args=[&quot;1&quot;])
'http://localhost:8000/api/users/1/set_password'
</code></pre>
<p>Alternatively, you can use the <code>url_name</code> attribute set by the <code>@action</code> decorator.</p>
<pre><code class="language-python">&gt;&gt;&gt; view.reverse_action(view.set_password.url_name, args=['1'])
<pre><code class="language-pycon">&gt;&gt;&gt; view.reverse_action(view.set_password.url_name, args=['1'])
'http://localhost:8000/api/users/1/set_password'
</code></pre>
<p>The <code>url_name</code> argument for <code>.reverse_action()</code> should match the same argument to the <code>@action</code> decorator. Additionally, this method can be used to reverse the default actions, such as <code>list</code> and <code>create</code>.</p>
@ -684,7 +688,7 @@ class UserViewSet(viewsets.ModelViewSet):
<p>In order to use a <code>GenericViewSet</code> class you'll override the class and either mixin the required mixin classes, or define the action implementations explicitly.</p>
<h2 id="modelviewset"><a class="toclink" href="#modelviewset">ModelViewSet</a></h2>
<p>The <code>ModelViewSet</code> class inherits from <code>GenericAPIView</code> and includes implementations for various actions, by mixing in the behavior of the various mixin classes.</p>
<p>The actions provided by the <code>ModelViewSet</code> class are <code>.list()</code>, <code>.retrieve()</code>, <code>.create()</code>, <code>.update()</code>, <code>.partial_update()</code>, and <code>.destroy()</code>.</p>
<p>The actions provided by the <code>ModelViewSet</code> class are <code>.list()</code>, <code>.retrieve()</code>, <code>.create()</code>, <code>.update()</code>, <code>.partial_update()</code>, and <code>.destroy()</code>.</p>
<h4 id="example_1"><a class="toclink" href="#example_1">Example</a></h4>
<p>Because <code>ModelViewSet</code> extends <code>GenericAPIView</code>, you'll normally need to provide at least the <code>queryset</code> and <code>serializer_class</code> attributes. For example:</p>
<pre><code>class AccountViewSet(viewsets.ModelViewSet):

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -490,7 +486,7 @@
<li>Support for overriding how validation errors are handled by your API.</li>
<li>A metadata API that allows you to customize how <code>OPTIONS</code> requests are handled by your API.</li>
<li>A more compact JSON output with unicode style encoding turned on by default.</li>
<li>Templated based HTML form rendering for serializers. This will be finalized as public API in the upcoming 3.1 release.</li>
<li>Templated based HTML form rendering for serializers. This will be finalized as public API in the upcoming 3.1 release.</li>
</ul>
<p>Significant new functionality continues to be planned for the 3.1 and 3.2 releases. These releases will correspond to the two <a href="https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3">Kickstarter stretch goals</a> - "Feature improvements" and "Admin interface". Further 3.x releases will present simple upgrades, without the same level of fundamental API changes necessary for the 3.0 release.</p>
<hr />
@ -970,7 +966,7 @@ def all_high_scores(request):
<p>The <code>MultipleChoiceField</code> class has been added. This field acts like <code>ChoiceField</code>, but returns a set, which may include none, one or many of the valid choices.</p>
<h4 id="changes-to-the-custom-field-api"><a class="toclink" href="#changes-to-the-custom-field-api">Changes to the custom field API.</a></h4>
<p>The <code>from_native(self, value)</code> and <code>to_native(self, data)</code> method names have been replaced with the more obviously named <code>to_internal_value(self, data)</code> and <code>to_representation(self, value)</code>.</p>
<p>The <code>field_from_native()</code> and <code>field_to_native()</code> methods are removed. Previously you could use these methods if you wanted to customise the behaviour in a way that did not simply lookup the field value from the object. For example...</p>
<p>The <code>field_from_native()</code> and <code>field_to_native()</code> methods are removed. Previously you could use these methods if you wanted to customise the behavior in a way that did not simply lookup the field value from the object. For example...</p>
<pre><code>def field_to_native(self, obj, field_name):
"""A custom read-only field that returns the class name."""
return obj.__class__.__name__

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -486,8 +482,8 @@
update your REST framework settings to include <code>DEFAULT_SCHEMA_CLASS</code> explicitly.</p>
<p><strong>settings.py</strong>:</p>
<pre><code class="language-python">REST_FRAMEWORK = {
...
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
...: ...,
&quot;DEFAULT_SCHEMA_CLASS&quot;: &quot;rest_framework.schemas.coreapi.AutoSchema&quot;,
}
</code></pre>
<p>You'll still be able to keep using CoreAPI schemas, API docs, and client for the
@ -495,7 +491,7 @@ foreseeable future. We'll aim to ensure that the CoreAPI schema generator remain
available as a third party package, even once it has eventually been removed
from REST framework, scheduled for version 3.12.</p>
<p>We have removed the old documentation for the CoreAPI based schema generation.
You may view the <a href="https://github.com/encode/django-rest-framework/blob/master/docs/coreapi/index.md">Legacy CoreAPI documentation here</a>.</p>
You may view the <a href="https://github.com/encode/django-rest-framework/blob/3.14.0/docs/coreapi/index.md">Legacy CoreAPI documentation here</a>.</p>
<hr />
<h2 id="openapi-quickstart"><a class="toclink" href="#openapi-quickstart">OpenAPI Quickstart</a></h2>
<p>You can generate a static OpenAPI schema, using the <code>generateschema</code> management
@ -510,10 +506,11 @@ urlpatterns = [
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
# * `title` and `description` parameters are passed to `SchemaGenerator`.
# * Provide view name for use with `reverse()`.
path('openapi', get_schema_view(
title=&quot;Your Project&quot;,
description=&quot;API for all things …&quot;
), name='openapi-schema'),
path(
&quot;openapi&quot;,
get_schema_view(title=&quot;Your Project&quot;, description=&quot;API for all things …&quot;),
name=&quot;openapi-schema&quot;,
),
# ...
]
</code></pre>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -484,10 +480,11 @@ include:</p>
<p>In this example view operation descriptions for the <code>get</code> and <code>post</code> methods will
be extracted from the class docstring:</p>
<pre><code class="language-python">class DocStringExampleListView(APIView):
&quot;&quot;&quot;
get: A description of my GET operation.
post: A description of my POST operation.
&quot;&quot;&quot;
&quot;&quot;&quot;
get: A description of my GET operation.
post: A description of my POST operation.
&quot;&quot;&quot;
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def get(self, request, *args, **kwargs):

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -441,6 +437,10 @@
<a href="#searchfilter-improvements">SearchFilter improvements</a>
</li>
<li>
<a href="#deprecations">Deprecations</a>
</li>
<li>
<a href="#funding">Funding</a>
</li>
@ -520,7 +520,7 @@ in the URL path.</p>
</table>
<p>The tags used for a particular view may also be overridden...</p>
<pre><code class="language-python">class MyOrders(APIView):
schema = AutoSchema(tags=['users', 'orders'])
schema = AutoSchema(tags=[&quot;users&quot;, &quot;orders&quot;])
...
</code></pre>
<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>
@ -537,7 +537,7 @@ 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>
<pre><code class="language-python">class MyOrders(APIView):
schema = AutoSchema(component_name=&quot;OrderDetails&quot;)
schema = AutoSchema(component_name=&quot;OrderDetails&quot;)
</code></pre>
<h2 id="more-public-api"><a class="toclink" href="#more-public-api">More Public API</a></h2>
<p>Many methods on the <code>AutoSchema</code> class have now been promoted to public API,
@ -576,10 +576,11 @@ search should apply to.</p>
by a search against the site name or location. (Location searches are
matched against the region and country names.)
&quot;&quot;&quot;
queryset = Sites.objects.all()
serializer_class = SitesSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['site_name', 'location__region', 'location__country']
search_fields = [&quot;site_name&quot;, &quot;location__region&quot;, &quot;location__country&quot;]
</code></pre>
<h3 id="searches-against-annotate-fields"><a class="toclink" href="#searches-against-annotate-fields">Searches against annotate fields</a></h3>
<p>Django allows querysets to create additional virtual fields, using the <code>.annotate</code>
@ -589,12 +590,18 @@ method. We now support searching against annotate fields.</p>
Search for publishers, optionally filtering the search against the average
rating of all their books.
&quot;&quot;&quot;
queryset = Publisher.objects.annotate(avg_rating=Avg('book__rating'))
queryset = Publisher.objects.annotate(avg_rating=Avg(&quot;book__rating&quot;))
serializer_class = PublisherSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['avg_rating']
search_fields = [&quot;avg_rating&quot;]
</code></pre>
<hr />
<h2 id="deprecations"><a class="toclink" href="#deprecations">Deprecations</a></h2>
<h3 id="serializersnullbooleanfield"><a class="toclink" href="#serializersnullbooleanfield"><code>serializers.NullBooleanField</code></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"><a class="toclink" href="#funding">Funding</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

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -441,6 +437,10 @@
<a href="#minor-fixes-and-improvements">Minor fixes and improvements</a>
</li>
<li>
<a href="#deprecations">Deprecations</a>
</li>
<div class="promo">
@ -501,6 +501,11 @@ skipped depending on the other arguments.</p>
<p>See Pull Request <a href="https://github.com/encode/django-rest-framework/pull/7522">#7522</a> for more details.</p>
<h2 id="minor-fixes-and-improvements"><a class="toclink" href="#minor-fixes-and-improvements">Minor fixes and improvements</a></h2>
<p>There are a number of minor fixes and improvements in this release. See the <a href="../release-notes/">release notes</a> page for a complete listing.</p>
<hr />
<h2 id="deprecations"><a class="toclink" href="#deprecations">Deprecations</a></h2>
<h3 id="serializersnullbooleanfield"><a class="toclink" href="#serializersnullbooleanfield"><code>serializers.NullBooleanField</code></a></h3>
<p><code>serializers.NullBooleanField</code> was moved to pending deprecation in 3.12, and deprecated in 3.13. It has now been removed from the core framework.</p>
<p>Instead use <code>serializers.BooleanField</code> field and set <code>allow_null=True</code> which does the same thing.</p>
</div> <!--/span-->

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -498,7 +494,7 @@
<p>There are a couple of bug fixes that are worth calling out as they introduce differing behavior.</p>
<p>These are a little subtle and probably won't affect most users, but are worth understanding before upgrading your project.</p>
<h3 id="manytomany-fields-and-blanktrue"><a class="toclink" href="#manytomany-fields-and-blanktrue">ManyToMany fields and blank=True</a></h3>
<p>We've now added an <code>allow_empty</code> argument, which can be used with <code>ListSerializer</code>, or with <code>many=True</code> relationships. This is <code>True</code> by default, but can be set to <code>False</code> if you want to disallow empty lists as valid input.</p>
<p>We've now added an <code>allow_empty</code> argument, which can be used with <code>ListSerializer</code>, or with <code>many=True</code> relationships. This is <code>True</code> by default, but can be set to <code>False</code> if you want to disallow empty lists as valid input.</p>
<p>As a follow-up to this we are now able to properly mirror the behavior of Django's <code>ModelForm</code> with respect to how many-to-many fields are validated.</p>
<p>Previously a many-to-many field on a model would map to a serializer field that would allow either empty or non-empty list inputs. Now, a many-to-many field will map to a serializer field that requires at least one input, unless the model field has <code>blank=True</code> set.</p>
<p>Here's what the mapping looks like in practice:</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -556,7 +552,7 @@ documentation generation and parameter annotation.</p>
<ul>
<li>New tutorial section on <a href="../tutorial/7-schemas-and-client-libraries/">schemas &amp; client libraries</a>.</li>
<li>Documentation page on <a href="../api-guide/schemas/">schema generation</a>.</li>
<li>Topic page on <a href="../../topics/api-clients/">API clients</a>.</li>
<li>Topic page on <a href="https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md">API clients</a>.</li>
</ul>
<p>It is also worth noting that Marc Gibbons is currently working towards a 2.0 release of
the popular Django REST Swagger package, which will tie in with our new built-in support.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -565,7 +561,7 @@ used by your project itself, or as an external client interacting with your API.
<p>The client is not limited to usage with REST framework APIs, although it does
currently only support loading CoreJSON API schemas. Support for Swagger and
other API schemas is planned.</p>
<p>For more details see the <a href="../../topics/api-clients/#javascript-client-library">JavaScript client library documentation</a>.</p>
<p>For more details see the <a href="https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md#javascript-client-library">JavaScript client library documentation</a>.</p>
<h2 id="authentication-classes-for-the-python-client-library"><a class="toclink" href="#authentication-classes-for-the-python-client-library">Authentication classes for the Python client library</a></h2>
<p>Previous authentication support in the Python client library was limited to
allowing users to provide explicit header values.</p>
@ -576,7 +572,7 @@ the introduction of the <code>BasicAuthentication</code>, <code>TokenAuthenticat
<pre><code>auth = coreapi.auth.TokenAuthentication(scheme='JWT', token='xxx-xxx-xxx')
client = coreapi.Client(auth=auth)
</code></pre>
<p>For more information see the <a href="../../topics/api-clients/#python-client-library">Python client library documentation</a>.</p>
<p>For more information see the <a href="https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md#python-client-library">Python client library documentation</a>.</p>
<hr />
<h2 id="deprecations"><a class="toclink" href="#deprecations">Deprecations</a></h2>
<h3 id="updating-coreapi"><a class="toclink" href="#updating-coreapi">Updating coreapi</a></h3>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -513,7 +509,7 @@ in 3.10.</p>
for a complete listing.</p>
<h2 id="whats-next"><a class="toclink" href="#whats-next">What's next</a></h2>
<p>We're currently working towards moving to using <a href="https://www.openapis.org/">OpenAPI</a> as our default schema output. We'll also be revisiting our API documentation generation and client libraries.</p>
<p>We're doing some consolidation in order to make this happen. It's planned that 3.9 will drop the <code>coreapi</code> and <code>coreschema</code> libraries, and instead use <code>apistar</code> for the API documentation generation, schema generation, and API client libraries.</p>
<p>We're doing some consolidation in order to make this happen. It's planned that 3.9 will drop the <code>coreapi</code> and <code>coreschema</code> libraries, and instead use <code>apistar</code> for the API documentation generation, schema generation, and API client libraries.</p>
</div> <!--/span-->

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -519,15 +515,12 @@ from rest_framework.renderers import JSONOpenAPIRenderer
from django.urls import path
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
renderer_classes=[JSONOpenAPIRenderer]
title=&quot;Server Monitoring API&quot;,
url=&quot;https://www.example.org/api/&quot;,
renderer_classes=[JSONOpenAPIRenderer],
)
urlpatterns = [
path('schema.json', schema_view),
...
]
urlpatterns = [path(&quot;schema.json&quot;, schema_view), ...]
</code></pre>
<p>And here's how you can use the <code>generateschema</code> management command:</p>
<pre><code class="language-shell">$ python manage.py generateschema --format openapi &gt; schema.yml

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -543,7 +539,7 @@ To set them up, first ensure you have the pre-commit tool installed, for example
<pre><code># Setup the virtual environment
python3 -m venv env
source env/bin/activate
pip install django
pip install -e .
pip install -r requirements.txt
# Run the tests

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -585,7 +581,7 @@ form.signup {
<h2 id="what-funding-has-enabled-so-far"><a class="toclink" href="#what-funding-has-enabled-so-far">What funding has enabled so far</a></h2>
<ul>
<li>The <a href="https://www.django-rest-framework.org/community/3.4-announcement/">3.4</a> and <a href="https://www.django-rest-framework.org/community/3.5-announcement/">3.5</a> releases, including schema generation for both Swagger and RAML, a Python client library, a Command Line client, and addressing of a large number of outstanding issues.</li>
<li>The <a href="https://www.django-rest-framework.org/community/3.6-announcement/">3.6</a> release, including JavaScript client library, and API documentation, complete with auto-generated code samples.</li>
<li>The <a href="https://www.django-rest-framework.org/community/3.6-announcement/">3.6</a> release, including JavaScript client library, and API documentation, complete with auto-generated code samples.</li>
<li>The <a href="https://www.django-rest-framework.org/community/3.7-announcement/">3.7 release</a>, made possible due to our collaborative funding model, focuses on improvements to schema generation and the interactive API documentation.</li>
<li>The recent <a href="https://www.django-rest-framework.org/community/3.8-announcement/">3.8 release</a>.</li>
<li>Tom Christie, the creator of Django REST framework, working on the project full-time.</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -449,8 +445,9 @@
<li><a href="https://stackoverflow.com/jobs/companies?tl=django">https://stackoverflow.com/jobs/companies?tl=django</a></li>
<li><a href="https://www.upwork.com/o/jobs/browse/skill/django-framework/">https://www.upwork.com/o/jobs/browse/skill/django-framework/</a></li>
<li><a href="https://www.technojobs.co.uk/django-jobs">https://www.technojobs.co.uk/django-jobs</a></li>
<li><a href="https://remoteok.io/remote-django-jobs">https://remoteok.io/remote-django-jobs</a></li>
<li><a href="https://remoteok.com/remote-django-jobs">https://remoteok.com/remote-django-jobs</a></li>
<li><a href="https://www.remotepython.com/jobs/">https://www.remotepython.com/jobs/</a></li>
<li><a href="https://www.pyjobs.com/">https://www.pyjobs.com/</a></li>
</ul>
<p>Know of any other great resources for Django REST Framework jobs that are missing in our list? Please <a href="https://github.com/encode/django-rest-framework">submit a pull request</a> or <a href="mailto:anna@django-rest-framework.org">email us</a>.</p>
<p>Wonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for <a href="https://fund.django-rest-framework.org/topics/funding/">REST Framework sponsorship</a> yet.</p>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -550,6 +546,9 @@ Checklist:
- [ ] `docs` Python &amp; Django versions
- [ ] Update the translations from [transifex](https://www.django-rest-framework.org/topics/project-management/#translations).
- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py).
- [ ] Ensure documentation validates
- Build and serve docs `mkdocs serve`
- Validate links `pylinkvalidate.py -P http://127.0.0.1:8000`
- [ ] Confirm with @tomchristie that release is finalized and ready to go.
- [ ] Ensure that release date is included in pull request.
- [ ] Merge the release pull request.

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -643,6 +639,7 @@
<li>Fix <code>PrimaryKeyRelatedField</code> and <code>HyperlinkedRelatedField</code> when source field is actually a property. [#7142]</li>
<li><code>Token.generate_key</code> is now a class method. [#7502]</li>
<li><code>@action</code> warns if method is wrapped in a decorator that does not preserve information using <code>@functools.wraps</code>. [#7098]</li>
<li>Deprecate <code>serializers.NullBooleanField</code> in favour of <code>serializers.BooleanField</code> with <code>allow_null=True</code> [#7122]</li>
</ul>
<hr />
<h2 id="311x-series"><a class="toclink" href="#311x-series">3.11.x series</a></h2>
@ -772,7 +769,11 @@ Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10.</
class NullableCharField(serializers.CharField):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]</code></li>
self.validators = [
v
for v in self.validators
if not isinstance(v, ProhibitNullCharactersValidator)
]</code></li>
<li>Add <code>OpenAPIRenderer</code> and <code>generate_schema</code> management command. <a href="https://github.com/encode/django-rest-framework/issues/6229">#6229</a></li>
<li>Add OpenAPIRenderer by default, and add schema docs. <a href="https://github.com/encode/django-rest-framework/issues/6233">#6233</a></li>
<li>Allow permissions to be composed <a href="https://github.com/encode/django-rest-framework/issues/5753">#5753</a></li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -545,7 +541,7 @@
<li><a href="https://github.com/philipn/django-rest-framework-chain">djangorestframework-chain</a> - Allows arbitrary chaining of both relations and lookup filters.</li>
<li><a href="https://github.com/miki725/django-url-filter">django-url-filter</a> - Allows a safe way to filter data via human-friendly URLs. It is a generic library which is not tied to DRF but it provides easy integration with DRF.</li>
<li><a href="https://github.com/manjitkumar/drf-url-filters">drf-url-filter</a> is a simple Django app to apply filters on drf <code>ModelViewSet</code>'s <code>Queryset</code> in a clean, simple and configurable way. It also supports validations on incoming query params and their values.</li>
<li><a href="https://github.com/rpkilby/django-rest-framework-guardian">django-rest-framework-guardian</a> - Provides integration with django-guardian, including the <code>DjangoObjectPermissionsFilter</code> previously found in DRF.</li>
<li><a href="https://github.com/johnthagen/django-rest-framework-guardian2">django-rest-framework-guardian2</a> - Provides integration with django-guardian, including the <code>DjangoObjectPermissionsFilter</code> previously found in DRF.</li>
</ul>
<h3 id="misc"><a class="toclink" href="#misc">Misc</a></h3>
<ul>
@ -574,6 +570,7 @@
<li><a href="https://github.com/iashraful/fast-drf">fast-drf</a> - A model based library for making API development faster and easier.</li>
<li><a href="https://github.com/Raekkeri/django-requestlogs">django-requestlogs</a> - Providing middleware and other helpers for audit logging for REST framework.</li>
<li><a href="https://github.com/ghazi-git/drf-standardized-errors">drf-standardized-errors</a> - DRF exception handler to standardize error responses for all API endpoints.</li>
<li><a href="https://github.com/Ori-Roza/drf-api-action">drf-api-action</a> - uses the power of DRF also as a library functions</li>
</ul>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -421,6 +417,10 @@
<a href="#books">Books</a>
</li>
<li>
<a href="#courses">Courses</a>
</li>
<li>
<a href="#tutorials">Tutorials</a>
</li>
@ -466,6 +466,10 @@
</a>
</div>
<h2 id="courses"><a class="toclink" href="#courses">Courses</a></h2>
<ul>
<li><a href="https://testdriven.io/courses/django-rest-framework/">Developing RESTful APIs with Django REST Framework</a></li>
</ul>
<h2 id="tutorials"><a class="toclink" href="#tutorials">Tutorials</a></h2>
<ul>
<li><a href="https://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786">Beginner's Guide to the Django REST Framework</a></li>

View File

@ -1,700 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Tutorial 7: Schemas & client libraries - Django REST framework</title>
<link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="https://www.django-rest-framework.org/coreapi/7-schemas-and-client-libraries/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST, Tutorial 7: Schemas & client libraries">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="../../css/prettify.css" rel="stylesheet">
<link href="../../css/bootstrap.css" rel="stylesheet">
<link href="../../css/bootstrap-responsive.css" rel="stylesheet">
<link href="../../css/default.css" rel="stylesheet">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#sidebarInclude img {
margin-bottom: 10px;
}
#sidebarInclude a.promo {
color: black;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
</style>
</head>
<body onload="prettyPrint()" class="-page">
<div class="wrapper">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="next" >
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="prev" >
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://www.django-rest-framework.org/">Django REST framework</a>
<div class="nav-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav">
<li >
<a href="../..">Home</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../tutorial/quickstart/">Quickstart</a>
</li>
<li >
<a href="../../tutorial/1-serialization/">1 - Serialization</a>
</li>
<li >
<a href="../../tutorial/2-requests-and-responses/">2 - Requests and responses</a>
</li>
<li >
<a href="../../tutorial/3-class-based-views/">3 - Class based views</a>
</li>
<li >
<a href="../../tutorial/4-authentication-and-permissions/">4 - Authentication and permissions</a>
</li>
<li >
<a href="../../tutorial/5-relationships-and-hyperlinked-apis/">5 - Relationships and hyperlinked APIs</a>
</li>
<li >
<a href="../../tutorial/6-viewsets-and-routers/">6 - Viewsets and routers</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../api-guide/requests/">Requests</a>
</li>
<li >
<a href="../../api-guide/responses/">Responses</a>
</li>
<li >
<a href="../../api-guide/views/">Views</a>
</li>
<li >
<a href="../../api-guide/generic-views/">Generic views</a>
</li>
<li >
<a href="../../api-guide/viewsets/">Viewsets</a>
</li>
<li >
<a href="../../api-guide/routers/">Routers</a>
</li>
<li >
<a href="../../api-guide/parsers/">Parsers</a>
</li>
<li >
<a href="../../api-guide/renderers/">Renderers</a>
</li>
<li >
<a href="../../api-guide/serializers/">Serializers</a>
</li>
<li >
<a href="../../api-guide/fields/">Serializer fields</a>
</li>
<li >
<a href="../../api-guide/relations/">Serializer relations</a>
</li>
<li >
<a href="../../api-guide/validators/">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication/">Authentication</a>
</li>
<li >
<a href="../../api-guide/permissions/">Permissions</a>
</li>
<li >
<a href="../../api-guide/caching/">Caching</a>
</li>
<li >
<a href="../../api-guide/throttling/">Throttling</a>
</li>
<li >
<a href="../../api-guide/filtering/">Filtering</a>
</li>
<li >
<a href="../../api-guide/pagination/">Pagination</a>
</li>
<li >
<a href="../../api-guide/versioning/">Versioning</a>
</li>
<li >
<a href="../../api-guide/content-negotiation/">Content negotiation</a>
</li>
<li >
<a href="../../api-guide/metadata/">Metadata</a>
</li>
<li >
<a href="../../api-guide/schemas/">Schemas</a>
</li>
<li >
<a href="../../api-guide/format-suffixes/">Format suffixes</a>
</li>
<li >
<a href="../../api-guide/reverse/">Returning URLs</a>
</li>
<li >
<a href="../../api-guide/exceptions/">Exceptions</a>
</li>
<li >
<a href="../../api-guide/status-codes/">Status codes</a>
</li>
<li >
<a href="../../api-guide/testing/">Testing</a>
</li>
<li >
<a href="../../api-guide/settings/">Settings</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
<li >
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
</li>
<li >
<a href="../../topics/html-and-forms/">HTML & Forms</a>
</li>
<li >
<a href="../../topics/browser-enhancements/">Browser Enhancements</a>
</li>
<li >
<a href="../../topics/browsable-api/">The Browsable API</a>
</li>
<li >
<a href="../../topics/rest-hypermedia-hateoas/">REST, Hypermedia & HATEOAS</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
</li>
<li >
<a href="../../community/third-party-packages/">Third Party Packages</a>
</li>
<li >
<a href="../../community/contributing/">Contributing to REST framework</a>
</li>
<li >
<a href="../../community/project-management/">Project management</a>
</li>
<li >
<a href="../../community/release-notes/">Release Notes</a>
</li>
<li >
<a href="../../community/3.14-announcement/">3.14 Announcement</a>
</li>
<li >
<a href="../../community/3.13-announcement/">3.13 Announcement</a>
</li>
<li >
<a href="../../community/3.12-announcement/">3.12 Announcement</a>
</li>
<li >
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
</li>
<li >
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
</li>
<li >
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
</li>
<li >
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
</li>
<li >
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
</li>
<li >
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
</li>
<li >
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
</li>
<li >
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
</li>
<li >
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
</li>
<li >
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
</li>
<li >
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
</li>
<li >
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
</li>
<li >
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
</li>
<li >
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
</li>
<li >
<a href="../../community/funding/">Funding</a>
</li>
<li >
<a href="../../community/jobs/">Jobs</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<div class="body-content">
<div class="container-fluid">
<!-- Search Modal -->
<div id="mkdocs_search_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="myModalLabel">Documentation search</h3>
</div>
<div class="modal-body">
<form role="form" autocomplete="off">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
</div>
</form>
<div id="mkdocs-search-results"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main">
<a href="#tutorial-7-schemas-client-libraries">Tutorial 7: Schemas &amp; client libraries</a>
</li>
<li>
<a href="#core-api">Core API</a>
</li>
<li>
<a href="#adding-a-schema">Adding a schema</a>
</li>
<li>
<a href="#using-a-command-line-client">Using a command line client</a>
</li>
<li>
<a href="#authenticating-our-client">Authenticating our client</a>
</li>
<li>
<a href="#reviewing-our-work">Reviewing our work</a>
</li>
<li>
<a href="#onwards-and-upwards">Onwards and upwards</a>
</li>
<div class="promo">
<hr/>
<div id="sidebarInclude">
</div>
</ul>
</div>
</div>
<div id="main-content" class="span9">
<h1 id="tutorial-7-schemas-client-libraries"><a class="toclink" href="#tutorial-7-schemas-client-libraries">Tutorial 7: Schemas &amp; client libraries</a></h1>
<hr />
<p><strong>DEPRECATION NOTICE:</strong> Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. See the <a href="../../community/3.10-announcement/">Version 3.10 Release Announcement</a> for more details.</p>
<p>If you are looking for information regarding schemas, you might want to look at these updated resources:</p>
<ol>
<li><a href="../../api-guide/schemas/">Schema</a></li>
<li><a href="../../topics/documenting-your-api/">Documenting your API</a></li>
</ol>
<hr />
<p>A schema is a machine-readable document that describes the available API
endpoints, their URLS, and what operations they support.</p>
<p>Schemas can be a useful tool for auto-generated documentation, and can also
be used to drive dynamic client libraries that can interact with the API.</p>
<h2 id="core-api"><a class="toclink" href="#core-api">Core API</a></h2>
<p>In order to provide schema support REST framework uses <a href="https://www.coreapi.org/">Core API</a>.</p>
<p>Core API is a document specification for describing APIs. It is used to provide
an internal representation format of the available endpoints and possible
interactions that an API exposes. It can either be used server-side, or
client-side.</p>
<p>When used server-side, Core API allows an API to support rendering to a wide
range of schema or hypermedia formats.</p>
<p>When used client-side, Core API allows for dynamically driven client libraries
that can interact with any API that exposes a supported schema or hypermedia
format.</p>
<h2 id="adding-a-schema"><a class="toclink" href="#adding-a-schema">Adding a schema</a></h2>
<p>REST framework supports either explicitly defined schema views, or
automatically generated schemas. Since we're using viewsets and routers,
we can simply use the automatic schema generation.</p>
<p>You'll need to install the <code>coreapi</code> python package in order to include an
API schema, and <code>pyyaml</code> to render the schema into the commonly used
YAML-based OpenAPI format.</p>
<pre><code>$ pip install coreapi pyyaml
</code></pre>
<p>We can now include a schema for our API, by including an autogenerated schema
view in our URL configuration.</p>
<pre><code class="language-python">from rest_framework.schemas import get_schema_view
schema_view = get_schema_view(title='Pastebin API')
urlpatterns = [
   path('schema/', schema_view),
...
]
</code></pre>
<p>If you visit the <code>/schema/</code> endpoint in a browser you should now see <code>corejson</code>
representation become available as an option.</p>
<p><img alt="Schema format" src="../../img/corejson-format.png" /></p>
<p>We can also request the schema from the command line, by specifying the desired
content type in the <code>Accept</code> header.</p>
<pre><code>$ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json
HTTP/1.0 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/coreapi+json
{
"_meta": {
"title": "Pastebin API"
},
"_type": "document",
...
</code></pre>
<p>The default output style is to use the <a href="https://www.coreapi.org/specification/encoding/#core-json-encoding">Core JSON</a> encoding.</p>
<p>Other schema formats, such as <a href="https://openapis.org/">Open API</a> (formerly Swagger) are
also supported.</p>
<h2 id="using-a-command-line-client"><a class="toclink" href="#using-a-command-line-client">Using a command line client</a></h2>
<p>Now that our API is exposing a schema endpoint, we can use a dynamic client
library to interact with the API. To demonstrate this, let's use the
Core API command line client.</p>
<p>The command line client is available as the <code>coreapi-cli</code> package:</p>
<pre><code>$ pip install coreapi-cli
</code></pre>
<p>Now check that it is available on the command line...</p>
<pre><code>$ coreapi
Usage: coreapi [OPTIONS] COMMAND [ARGS]...
Command line client for interacting with CoreAPI services.
Visit https://www.coreapi.org/ for more information.
Options:
--version Display the package version number.
--help Show this message and exit.
Commands:
...
</code></pre>
<p>First we'll load the API schema using the command line client.</p>
<pre><code>$ coreapi get http://127.0.0.1:8000/schema/
&lt;Pastebin API "http://127.0.0.1:8000/schema/"&gt;
snippets: {
highlight(id)
list()
read(id)
}
users: {
list()
read(id)
}
</code></pre>
<p>We haven't authenticated yet, so right now we're only able to see the read only
endpoints, in line with how we've set up the permissions on the API.</p>
<p>Let's try listing the existing snippets, using the command line client:</p>
<pre><code>$ coreapi action snippets list
[
{
"url": "http://127.0.0.1:8000/snippets/1/",
"id": 1,
"highlight": "http://127.0.0.1:8000/snippets/1/highlight/",
"owner": "lucy",
"title": "Example",
"code": "print('hello, world!')",
"linenos": true,
"language": "python",
"style": "friendly"
},
...
</code></pre>
<p>Some of the API endpoints require named parameters. For example, to get back
the highlight HTML for a particular snippet we need to provide an id.</p>
<pre><code>$ coreapi action snippets highlight --param id=1
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Example&lt;/title&gt;
...
</code></pre>
<h2 id="authenticating-our-client"><a class="toclink" href="#authenticating-our-client">Authenticating our client</a></h2>
<p>If we want to be able to create, edit and delete snippets, we'll need to
authenticate as a valid user. In this case we'll just use basic auth.</p>
<p>Make sure to replace the <code>&lt;username&gt;</code> and <code>&lt;password&gt;</code> below with your
actual username and password.</p>
<pre><code>$ coreapi credentials add 127.0.0.1 &lt;username&gt;:&lt;password&gt; --auth basic
Added credentials
127.0.0.1 "Basic &lt;...&gt;"
</code></pre>
<p>Now if we fetch the schema again, we should be able to see the full
set of available interactions.</p>
<pre><code>$ coreapi reload
Pastebin API "http://127.0.0.1:8000/schema/"&gt;
snippets: {
create(code, [title], [linenos], [language], [style])
delete(id)
highlight(id)
list()
partial_update(id, [title], [code], [linenos], [language], [style])
read(id)
update(id, code, [title], [linenos], [language], [style])
}
users: {
list()
read(id)
}
</code></pre>
<p>We're now able to interact with these endpoints. For example, to create a new
snippet:</p>
<pre><code>$ coreapi action snippets create --param title="Example" --param code="print('hello, world')"
{
"url": "http://127.0.0.1:8000/snippets/7/",
"id": 7,
"highlight": "http://127.0.0.1:8000/snippets/7/highlight/",
"owner": "lucy",
"title": "Example",
"code": "print('hello, world')",
"linenos": false,
"language": "python",
"style": "friendly"
}
</code></pre>
<p>And to delete a snippet:</p>
<pre><code>$ coreapi action snippets delete --param id=7
</code></pre>
<p>As well as the command line client, developers can also interact with your
API using client libraries. The Python client library is the first of these
to be available, and a Javascript client library is planned to be released
soon.</p>
<p>For more details on customizing schema generation and using Core API
client libraries you'll need to refer to the full documentation.</p>
<h2 id="reviewing-our-work"><a class="toclink" href="#reviewing-our-work">Reviewing our work</a></h2>
<p>With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, includes a schema-driven client library, and comes complete with authentication, per-object permissions, and multiple renderer formats.</p>
<p>We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.</p>
<p>You can review the final <a href="https://github.com/encode/rest-framework-tutorial">tutorial code</a> on GitHub, or try out a live example in <a href="https://restframework.herokuapp.com/">the sandbox</a>.</p>
<h2 id="onwards-and-upwards"><a class="toclink" href="#onwards-and-upwards">Onwards and upwards</a></h2>
<p>We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here are a few places you can start:</p>
<ul>
<li>Contribute on <a href="https://github.com/encode/django-rest-framework">GitHub</a> by reviewing and submitting issues, and making pull requests.</li>
<li>Join the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, and help build the community.</li>
<li>Follow <a href="https://twitter.com/_tomchristie">the author</a> on Twitter and say hi.</li>
</ul>
<p><strong>Now go build awesome things.</strong></p>
</div> <!--/span-->
</div> <!--/row-->
</div> <!--/.fluid-container-->
</div> <!--/.body content-->
<div id="push"></div>
</div> <!--/.wrapper -->
<footer class="span12">
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
</p>
</footer>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
<script src="../../js/jquery-1.8.1-min.js"></script>
<script src="../../js/prettify-1.0.js"></script>
<script src="../../js/bootstrap-2.1.1-min.js"></script>
<script src="../../js/theme.js"></script>
<script>var base_url = '../..';</script>
<script src="../../search/main.js" defer></script>
<script>
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav/dropdown to no higher than browser window
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
});
});
</script>
</body>
</html>

View File

@ -1,653 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>From documenting your api - Django REST framework</title>
<link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="https://www.django-rest-framework.org/coreapi/from-documenting-your-api/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST, From documenting your api">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="../../css/prettify.css" rel="stylesheet">
<link href="../../css/bootstrap.css" rel="stylesheet">
<link href="../../css/bootstrap-responsive.css" rel="stylesheet">
<link href="../../css/default.css" rel="stylesheet">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#sidebarInclude img {
margin-bottom: 10px;
}
#sidebarInclude a.promo {
color: black;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
</style>
</head>
<body onload="prettyPrint()" class="-page">
<div class="wrapper">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="next" >
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="prev" >
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://www.django-rest-framework.org/">Django REST framework</a>
<div class="nav-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav">
<li >
<a href="../..">Home</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../tutorial/quickstart/">Quickstart</a>
</li>
<li >
<a href="../../tutorial/1-serialization/">1 - Serialization</a>
</li>
<li >
<a href="../../tutorial/2-requests-and-responses/">2 - Requests and responses</a>
</li>
<li >
<a href="../../tutorial/3-class-based-views/">3 - Class based views</a>
</li>
<li >
<a href="../../tutorial/4-authentication-and-permissions/">4 - Authentication and permissions</a>
</li>
<li >
<a href="../../tutorial/5-relationships-and-hyperlinked-apis/">5 - Relationships and hyperlinked APIs</a>
</li>
<li >
<a href="../../tutorial/6-viewsets-and-routers/">6 - Viewsets and routers</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../api-guide/requests/">Requests</a>
</li>
<li >
<a href="../../api-guide/responses/">Responses</a>
</li>
<li >
<a href="../../api-guide/views/">Views</a>
</li>
<li >
<a href="../../api-guide/generic-views/">Generic views</a>
</li>
<li >
<a href="../../api-guide/viewsets/">Viewsets</a>
</li>
<li >
<a href="../../api-guide/routers/">Routers</a>
</li>
<li >
<a href="../../api-guide/parsers/">Parsers</a>
</li>
<li >
<a href="../../api-guide/renderers/">Renderers</a>
</li>
<li >
<a href="../../api-guide/serializers/">Serializers</a>
</li>
<li >
<a href="../../api-guide/fields/">Serializer fields</a>
</li>
<li >
<a href="../../api-guide/relations/">Serializer relations</a>
</li>
<li >
<a href="../../api-guide/validators/">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication/">Authentication</a>
</li>
<li >
<a href="../../api-guide/permissions/">Permissions</a>
</li>
<li >
<a href="../../api-guide/caching/">Caching</a>
</li>
<li >
<a href="../../api-guide/throttling/">Throttling</a>
</li>
<li >
<a href="../../api-guide/filtering/">Filtering</a>
</li>
<li >
<a href="../../api-guide/pagination/">Pagination</a>
</li>
<li >
<a href="../../api-guide/versioning/">Versioning</a>
</li>
<li >
<a href="../../api-guide/content-negotiation/">Content negotiation</a>
</li>
<li >
<a href="../../api-guide/metadata/">Metadata</a>
</li>
<li >
<a href="../../api-guide/schemas/">Schemas</a>
</li>
<li >
<a href="../../api-guide/format-suffixes/">Format suffixes</a>
</li>
<li >
<a href="../../api-guide/reverse/">Returning URLs</a>
</li>
<li >
<a href="../../api-guide/exceptions/">Exceptions</a>
</li>
<li >
<a href="../../api-guide/status-codes/">Status codes</a>
</li>
<li >
<a href="../../api-guide/testing/">Testing</a>
</li>
<li >
<a href="../../api-guide/settings/">Settings</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
<li >
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
</li>
<li >
<a href="../../topics/html-and-forms/">HTML & Forms</a>
</li>
<li >
<a href="../../topics/browser-enhancements/">Browser Enhancements</a>
</li>
<li >
<a href="../../topics/browsable-api/">The Browsable API</a>
</li>
<li >
<a href="../../topics/rest-hypermedia-hateoas/">REST, Hypermedia & HATEOAS</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
</li>
<li >
<a href="../../community/third-party-packages/">Third Party Packages</a>
</li>
<li >
<a href="../../community/contributing/">Contributing to REST framework</a>
</li>
<li >
<a href="../../community/project-management/">Project management</a>
</li>
<li >
<a href="../../community/release-notes/">Release Notes</a>
</li>
<li >
<a href="../../community/3.14-announcement/">3.14 Announcement</a>
</li>
<li >
<a href="../../community/3.13-announcement/">3.13 Announcement</a>
</li>
<li >
<a href="../../community/3.12-announcement/">3.12 Announcement</a>
</li>
<li >
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
</li>
<li >
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
</li>
<li >
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
</li>
<li >
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
</li>
<li >
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
</li>
<li >
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
</li>
<li >
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
</li>
<li >
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
</li>
<li >
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
</li>
<li >
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
</li>
<li >
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
</li>
<li >
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
</li>
<li >
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
</li>
<li >
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
</li>
<li >
<a href="../../community/funding/">Funding</a>
</li>
<li >
<a href="../../community/jobs/">Jobs</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<div class="body-content">
<div class="container-fluid">
<!-- Search Modal -->
<div id="mkdocs_search_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="myModalLabel">Documentation search</h3>
</div>
<div class="modal-body">
<form role="form" autocomplete="off">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
</div>
</form>
<div id="mkdocs-search-results"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main">
<a href="#built-in-api-documentation">Built-in API documentation</a>
</li>
<li>
<a href="#installation">Installation</a>
</li>
<li>
<a href="#documenting-your-views">Documenting your views</a>
</li>
<li>
<a href="#documentation-api-reference">documentation API Reference</a>
</li>
<li>
<a href="#customising-code-samples">Customising code samples</a>
</li>
<div class="promo">
<hr/>
<div id="sidebarInclude">
</div>
</ul>
</div>
</div>
<div id="main-content" class="span9">
<h2 id="built-in-api-documentation"><a class="toclink" href="#built-in-api-documentation">Built-in API documentation</a></h2>
<hr />
<p><strong>DEPRECATION NOTICE:</strong> Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. See the <a href="../../community/3.10-announcement/">Version 3.10 Release Announcement</a> for more details.</p>
<p>If you are looking for information regarding schemas, you might want to look at these updated resources:</p>
<ol>
<li><a href="../../api-guide/schemas/">Schema</a></li>
<li><a href="../../topics/documenting-your-api/">Documenting your API</a></li>
</ol>
<hr />
<p>The built-in API documentation includes:</p>
<ul>
<li>Documentation of API endpoints.</li>
<li>Automatically generated code samples for each of the available API client libraries.</li>
<li>Support for API interaction.</li>
</ul>
<h3 id="installation"><a class="toclink" href="#installation">Installation</a></h3>
<p>The <code>coreapi</code> library is required as a dependency for the API docs. Make sure
to install the latest version. The <code>Pygments</code> and <code>Markdown</code> libraries
are optional but recommended.</p>
<p>To install the API documentation, you'll need to include it in your project's URLconf:</p>
<pre><code>from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
path('docs/', include_docs_urls(title='My API title'))
]
</code></pre>
<p>This will include two different views:</p>
<ul>
<li><code>/docs/</code> - The documentation page itself.</li>
<li><code>/docs/schema.js</code> - A JavaScript resource that exposes the API schema.</li>
</ul>
<hr />
<p><strong>Note</strong>: By default <code>include_docs_urls</code> configures the underlying <code>SchemaView</code> to generate <em>public</em> schemas.
This means that views will not be instantiated with a <code>request</code> instance. i.e. Inside the view <code>self.request</code> will be <code>None</code>.</p>
<p>To be compatible with this behaviour, methods (such as <code>get_serializer</code> or <code>get_serializer_class</code> etc.) which inspect <code>self.request</code> or, particularly, <code>self.request.user</code> may need to be adjusted to handle this case.</p>
<p>You may ensure views are given a <code>request</code> instance by calling <code>include_docs_urls</code> with <code>public=False</code>:</p>
<pre><code>from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
# Generate schema with valid `request` instance:
path('docs/', include_docs_urls(title='My API title', public=False))
]
</code></pre>
<hr />
<h3 id="documenting-your-views"><a class="toclink" href="#documenting-your-views">Documenting your views</a></h3>
<p>You can document your views by including docstrings that describe each of the available actions.
For example:</p>
<pre><code>class UserList(generics.ListAPIView):
"""
Return a list of all the existing users.
"""
</code></pre>
<p>If a view supports multiple methods, you should split your documentation using <code>method:</code> style delimiters.</p>
<pre><code>class UserList(generics.ListCreateAPIView):
"""
get:
Return a list of all the existing users.
post:
Create a new user instance.
"""
</code></pre>
<p>When using viewsets, you should use the relevant action names as delimiters.</p>
<pre><code>class UserViewSet(viewsets.ModelViewSet):
"""
retrieve:
Return the given user.
list:
Return a list of all the existing users.
create:
Create a new user instance.
"""
</code></pre>
<p>Custom actions on viewsets can also be documented in a similar way using the method names
as delimiters or by attaching the documentation to action mapping methods.</p>
<pre><code>class UserViewSet(viewsets.ModelViewset):
...
@action(detail=False, methods=['get', 'post'])
def some_action(self, request, *args, **kwargs):
"""
get:
A description of the get method on the custom action.
post:
A description of the post method on the custom action.
"""
@some_action.mapping.put
def put_some_action():
"""
A description of the put method on the custom action.
"""
</code></pre>
<h3 id="documentation-api-reference"><a class="toclink" href="#documentation-api-reference"><code>documentation</code> API Reference</a></h3>
<p>The <code>rest_framework.documentation</code> module provides three helper functions to help configure the interactive API documentation, <code>include_docs_urls</code> (usage shown above), <code>get_docs_view</code> and <code>get_schemajs_view</code>.</p>
<p><code>include_docs_urls</code> employs <code>get_docs_view</code> and <code>get_schemajs_view</code> to generate the url patterns for the documentation page and JavaScript resource that exposes the API schema respectively. They expose the following options for customisation. (<code>get_docs_view</code> and <code>get_schemajs_view</code> ultimately call <code>rest_frameworks.schemas.get_schema_view()</code>, see the Schemas docs for more options there.)</p>
<h4 id="include_docs_urls"><a class="toclink" href="#include_docs_urls"><code>include_docs_urls</code></a></h4>
<ul>
<li><code>title</code>: Default <code>None</code>. May be used to provide a descriptive title for the schema definition.</li>
<li><code>description</code>: Default <code>None</code>. May be used to provide a description for the schema definition.</li>
<li><code>schema_url</code>: Default <code>None</code>. May be used to pass a canonical base URL for the schema.</li>
<li><code>public</code>: Default <code>True</code>. Should the schema be considered <em>public</em>? If <code>True</code> schema is generated without a <code>request</code> instance being passed to views.</li>
<li><code>patterns</code>: Default <code>None</code>. A list of URLs to inspect when generating the schema. If <code>None</code> project's URL conf will be used.</li>
<li><code>generator_class</code>: Default <code>rest_framework.schemas.SchemaGenerator</code>. May be used to specify a <code>SchemaGenerator</code> subclass to be passed to the <code>SchemaView</code>.</li>
<li><code>authentication_classes</code>: Default <code>api_settings.DEFAULT_AUTHENTICATION_CLASSES</code>. May be used to pass custom authentication classes to the <code>SchemaView</code>.</li>
<li><code>permission_classes</code>: Default <code>api_settings.DEFAULT_PERMISSION_CLASSES</code> May be used to pass custom permission classes to the <code>SchemaView</code>.</li>
<li><code>renderer_classes</code>: Default <code>None</code>. May be used to pass custom renderer classes to the <code>SchemaView</code>.</li>
</ul>
<h4 id="get_docs_view"><a class="toclink" href="#get_docs_view"><code>get_docs_view</code></a></h4>
<ul>
<li><code>title</code>: Default <code>None</code>. May be used to provide a descriptive title for the schema definition.</li>
<li><code>description</code>: Default <code>None</code>. May be used to provide a description for the schema definition.</li>
<li><code>schema_url</code>: Default <code>None</code>. May be used to pass a canonical base URL for the schema.</li>
<li><code>public</code>: Default <code>True</code>. If <code>True</code> schema is generated without a <code>request</code> instance being passed to views.</li>
<li><code>patterns</code>: Default <code>None</code>. A list of URLs to inspect when generating the schema. If <code>None</code> project's URL conf will be used.</li>
<li><code>generator_class</code>: Default <code>rest_framework.schemas.SchemaGenerator</code>. May be used to specify a <code>SchemaGenerator</code> subclass to be passed to the <code>SchemaView</code>.</li>
<li><code>authentication_classes</code>: Default <code>api_settings.DEFAULT_AUTHENTICATION_CLASSES</code>. May be used to pass custom authentication classes to the <code>SchemaView</code>.</li>
<li><code>permission_classes</code>: Default <code>api_settings.DEFAULT_PERMISSION_CLASSES</code>. May be used to pass custom permission classes to the <code>SchemaView</code>.</li>
<li><code>renderer_classes</code>: Default <code>None</code>. May be used to pass custom renderer classes to the <code>SchemaView</code>. If <code>None</code> the <code>SchemaView</code> will be configured with <code>DocumentationRenderer</code> and <code>CoreJSONRenderer</code> renderers, corresponding to the (default) <code>html</code> and <code>corejson</code> formats.</li>
</ul>
<h4 id="get_schemajs_view"><a class="toclink" href="#get_schemajs_view"><code>get_schemajs_view</code></a></h4>
<ul>
<li><code>title</code>: Default <code>None</code>. May be used to provide a descriptive title for the schema definition.</li>
<li><code>description</code>: Default <code>None</code>. May be used to provide a description for the schema definition.</li>
<li><code>schema_url</code>: Default <code>None</code>. May be used to pass a canonical base URL for the schema.</li>
<li><code>public</code>: Default <code>True</code>. If <code>True</code> schema is generated without a <code>request</code> instance being passed to views.</li>
<li><code>patterns</code>: Default <code>None</code>. A list of URLs to inspect when generating the schema. If <code>None</code> project's URL conf will be used.</li>
<li><code>generator_class</code>: Default <code>rest_framework.schemas.SchemaGenerator</code>. May be used to specify a <code>SchemaGenerator</code> subclass to be passed to the <code>SchemaView</code>.</li>
<li><code>authentication_classes</code>: Default <code>api_settings.DEFAULT_AUTHENTICATION_CLASSES</code>. May be used to pass custom authentication classes to the <code>SchemaView</code>.</li>
<li><code>permission_classes</code>: Default <code>api_settings.DEFAULT_PERMISSION_CLASSES</code> May be used to pass custom permission classes to the <code>SchemaView</code>.</li>
</ul>
<h3 id="customising-code-samples"><a class="toclink" href="#customising-code-samples">Customising code samples</a></h3>
<p>The built-in API documentation includes automatically generated code samples for
each of the available API client libraries.</p>
<p>You may customise these samples by subclassing <code>DocumentationRenderer</code>, setting
<code>languages</code> to the list of languages you wish to support:</p>
<pre><code>from rest_framework.renderers import DocumentationRenderer
class CustomRenderer(DocumentationRenderer):
languages = ['ruby', 'go']
</code></pre>
<p>For each language you need to provide an <code>intro</code> template, detailing installation instructions and such,
plus a generic template for making API requests, that can be filled with individual request details.
See the <a href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/templates/rest_framework/docs/langs">templates for the bundled languages</a> for examples.</p>
<hr />
</div> <!--/span-->
</div> <!--/row-->
</div> <!--/.fluid-container-->
</div> <!--/.body content-->
<div id="push"></div>
</div> <!--/.wrapper -->
<footer class="span12">
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
</p>
</footer>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
<script src="../../js/jquery-1.8.1-min.js"></script>
<script src="../../js/prettify-1.0.js"></script>
<script src="../../js/bootstrap-2.1.1-min.js"></script>
<script src="../../js/theme.js"></script>
<script>var base_url = '../..';</script>
<script src="../../search/main.js" defer></script>
<script>
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav/dropdown to no higher than browser window
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
});
});
</script>
</body>
</html>

View File

@ -1,506 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Legacy CoreAPI Schemas Docs - Django REST framework</title>
<link href="../img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="https://www.django-rest-framework.org/coreapi/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST, Legacy CoreAPI Schemas Docs">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="../css/prettify.css" rel="stylesheet">
<link href="../css/bootstrap.css" rel="stylesheet">
<link href="../css/bootstrap-responsive.css" rel="stylesheet">
<link href="../css/default.css" rel="stylesheet">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#sidebarInclude img {
margin-bottom: 10px;
}
#sidebarInclude a.promo {
color: black;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
</style>
</head>
<body onload="prettyPrint()" class="-page">
<div class="wrapper">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="next" >
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small disabled" rel="prev" >
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://www.django-rest-framework.org/">Django REST framework</a>
<div class="nav-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav">
<li >
<a href="..">Home</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../tutorial/quickstart/">Quickstart</a>
</li>
<li >
<a href="../tutorial/1-serialization/">1 - Serialization</a>
</li>
<li >
<a href="../tutorial/2-requests-and-responses/">2 - Requests and responses</a>
</li>
<li >
<a href="../tutorial/3-class-based-views/">3 - Class based views</a>
</li>
<li >
<a href="../tutorial/4-authentication-and-permissions/">4 - Authentication and permissions</a>
</li>
<li >
<a href="../tutorial/5-relationships-and-hyperlinked-apis/">5 - Relationships and hyperlinked APIs</a>
</li>
<li >
<a href="../tutorial/6-viewsets-and-routers/">6 - Viewsets and routers</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../api-guide/requests/">Requests</a>
</li>
<li >
<a href="../api-guide/responses/">Responses</a>
</li>
<li >
<a href="../api-guide/views/">Views</a>
</li>
<li >
<a href="../api-guide/generic-views/">Generic views</a>
</li>
<li >
<a href="../api-guide/viewsets/">Viewsets</a>
</li>
<li >
<a href="../api-guide/routers/">Routers</a>
</li>
<li >
<a href="../api-guide/parsers/">Parsers</a>
</li>
<li >
<a href="../api-guide/renderers/">Renderers</a>
</li>
<li >
<a href="../api-guide/serializers/">Serializers</a>
</li>
<li >
<a href="../api-guide/fields/">Serializer fields</a>
</li>
<li >
<a href="../api-guide/relations/">Serializer relations</a>
</li>
<li >
<a href="../api-guide/validators/">Validators</a>
</li>
<li >
<a href="../api-guide/authentication/">Authentication</a>
</li>
<li >
<a href="../api-guide/permissions/">Permissions</a>
</li>
<li >
<a href="../api-guide/caching/">Caching</a>
</li>
<li >
<a href="../api-guide/throttling/">Throttling</a>
</li>
<li >
<a href="../api-guide/filtering/">Filtering</a>
</li>
<li >
<a href="../api-guide/pagination/">Pagination</a>
</li>
<li >
<a href="../api-guide/versioning/">Versioning</a>
</li>
<li >
<a href="../api-guide/content-negotiation/">Content negotiation</a>
</li>
<li >
<a href="../api-guide/metadata/">Metadata</a>
</li>
<li >
<a href="../api-guide/schemas/">Schemas</a>
</li>
<li >
<a href="../api-guide/format-suffixes/">Format suffixes</a>
</li>
<li >
<a href="../api-guide/reverse/">Returning URLs</a>
</li>
<li >
<a href="../api-guide/exceptions/">Exceptions</a>
</li>
<li >
<a href="../api-guide/status-codes/">Status codes</a>
</li>
<li >
<a href="../api-guide/testing/">Testing</a>
</li>
<li >
<a href="../api-guide/settings/">Settings</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../topics/internationalization/">Internationalization</a>
</li>
<li >
<a href="../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
</li>
<li >
<a href="../topics/html-and-forms/">HTML & Forms</a>
</li>
<li >
<a href="../topics/browser-enhancements/">Browser Enhancements</a>
</li>
<li >
<a href="../topics/browsable-api/">The Browsable API</a>
</li>
<li >
<a href="../topics/rest-hypermedia-hateoas/">REST, Hypermedia & HATEOAS</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../community/tutorials-and-resources/">Tutorials and Resources</a>
</li>
<li >
<a href="../community/third-party-packages/">Third Party Packages</a>
</li>
<li >
<a href="../community/contributing/">Contributing to REST framework</a>
</li>
<li >
<a href="../community/project-management/">Project management</a>
</li>
<li >
<a href="../community/release-notes/">Release Notes</a>
</li>
<li >
<a href="../community/3.14-announcement/">3.14 Announcement</a>
</li>
<li >
<a href="../community/3.13-announcement/">3.13 Announcement</a>
</li>
<li >
<a href="../community/3.12-announcement/">3.12 Announcement</a>
</li>
<li >
<a href="../community/3.11-announcement/">3.11 Announcement</a>
</li>
<li >
<a href="../community/3.10-announcement/">3.10 Announcement</a>
</li>
<li >
<a href="../community/3.9-announcement/">3.9 Announcement</a>
</li>
<li >
<a href="../community/3.8-announcement/">3.8 Announcement</a>
</li>
<li >
<a href="../community/3.7-announcement/">3.7 Announcement</a>
</li>
<li >
<a href="../community/3.6-announcement/">3.6 Announcement</a>
</li>
<li >
<a href="../community/3.5-announcement/">3.5 Announcement</a>
</li>
<li >
<a href="../community/3.4-announcement/">3.4 Announcement</a>
</li>
<li >
<a href="../community/3.3-announcement/">3.3 Announcement</a>
</li>
<li >
<a href="../community/3.2-announcement/">3.2 Announcement</a>
</li>
<li >
<a href="../community/3.1-announcement/">3.1 Announcement</a>
</li>
<li >
<a href="../community/3.0-announcement/">3.0 Announcement</a>
</li>
<li >
<a href="../community/kickstarter-announcement/">Kickstarter Announcement</a>
</li>
<li >
<a href="../community/mozilla-grant/">Mozilla Grant</a>
</li>
<li >
<a href="../community/funding/">Funding</a>
</li>
<li >
<a href="../community/jobs/">Jobs</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<div class="body-content">
<div class="container-fluid">
<!-- Search Modal -->
<div id="mkdocs_search_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="myModalLabel">Documentation search</h3>
</div>
<div class="modal-body">
<form role="form" autocomplete="off">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
</div>
</form>
<div id="mkdocs-search-results"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main">
<a href="#legacy-coreapi-schemas-docs">Legacy CoreAPI Schemas Docs</a>
</li>
<div class="promo">
<hr/>
<div id="sidebarInclude">
</div>
</ul>
</div>
</div>
<div id="main-content" class="span9">
<h1 id="legacy-coreapi-schemas-docs"><a class="toclink" href="#legacy-coreapi-schemas-docs">Legacy CoreAPI Schemas Docs</a></h1>
<p>Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10.</p>
<p>See the <a href="../community/3.10-announcement/">Version 3.10 Release Announcement</a> for more details.</p>
<hr />
<p>You can continue to use CoreAPI schemas by setting the appropriate default schema class:</p>
<pre><code class="language-python"># In settings.py
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
</code></pre>
<p>Under-the-hood, any subclass of <code>coreapi.AutoSchema</code> here will trigger use of the old CoreAPI schemas.
<strong>Otherwise</strong> you will automatically be opted-in to the new OpenAPI schemas.</p>
<p>All CoreAPI related code will be removed in Django REST Framework v3.12. Switch to OpenAPI schemas by then.</p>
<hr />
<p>For reference this folder contains the old CoreAPI related documentation:</p>
<ul>
<li><a href="https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//7-schemas-and-client-libraries.md">Tutorial 7: Schemas &amp; client libraries</a>.</li>
<li><a href="https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//from-documenting-your-api.md">Excerpts from <em>Documenting your API</em> topic page</a>.</li>
<li><a href="https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//schemas.md"><code>rest_framework.schemas</code> API Reference</a>.</li>
</ul>
</div> <!--/span-->
</div> <!--/row-->
</div> <!--/.fluid-container-->
</div> <!--/.body content-->
<div id="push"></div>
</div> <!--/.wrapper -->
<footer class="span12">
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
</p>
</footer>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
<script src="../js/jquery-1.8.1-min.js"></script>
<script src="../js/prettify-1.0.js"></script>
<script src="../js/bootstrap-2.1.1-min.js"></script>
<script src="../js/theme.js"></script>
<script>var base_url = '..';</script>
<script src="../search/main.js" defer></script>
<script>
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav/dropdown to no higher than browser window
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
});
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -238,10 +238,6 @@
<a href="topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="topics/api-clients/">API Clients</a>
</li>
<li >
<a href="topics/internationalization/">Internationalization</a>
</li>
@ -554,16 +550,17 @@ continued development by <strong><a href="community/funding/">signing up for a p
<li><a href="https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/135996800-d49fe024-32d9-441a-98d9-4c7596287a67.png)">PostHog</a></li>
<li><a href="https://cryptapi.io" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cryptapi.png)">CryptAPI</a></li>
<li><a href="https://www.fezto.xyz/?utm_source=DjangoRESTFramework" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/fezto.png)">FEZTO</a></li>
<li><a href="https://www.svix.com/?utm_source=django-REST&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/svix.png)">Svix</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=DjangoRESTFramework&amp;utm_medium=Webpage_Logo_Ad&amp;utm_content=Developer&amp;utm_campaign=DjangoRESTFramework_Jan2022_HomePage">Stream</a>, <a href="https://www.spacinov.com/">Spacinov</a>, <a href="https://retool.com/?utm_source=djangorest&amp;utm_medium=sponsorship">Retool</a>, <a href="https://bit.io/jobs?utm_source=DRF&amp;utm_medium=sponsor&amp;utm_campaign=DRF_sponsorship">bit.io</a>, <a href="https://posthog.com?utm_source=DRF&amp;utm_medium=sponsor&amp;utm_campaign=DRF_sponsorship">PostHog</a>, <a href="https://cryptapi.io">CryptAPI</a>, and <a href="https://www.fezto.xyz/?utm_source=DjangoRESTFramework">FEZTO</a>.</em></p>
<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=DjangoRESTFramework&amp;utm_medium=Webpage_Logo_Ad&amp;utm_content=Developer&amp;utm_campaign=DjangoRESTFramework_Jan2022_HomePage">Stream</a>, <a href="https://www.spacinov.com/">Spacinov</a>, <a href="https://retool.com/?utm_source=djangorest&amp;utm_medium=sponsorship">Retool</a>, <a href="https://bit.io/jobs?utm_source=DRF&amp;utm_medium=sponsor&amp;utm_campaign=DRF_sponsorship">bit.io</a>, <a href="https://posthog.com?utm_source=DRF&amp;utm_medium=sponsor&amp;utm_campaign=DRF_sponsorship">PostHog</a>, <a href="https://cryptapi.io">CryptAPI</a>, <a href="https://www.fezto.xyz/?utm_source=DjangoRESTFramework">FEZTO</a>, and <a href="https://www.svix.com/?utm_source=django-REST&amp;utm_medium=sponsorship">Svix</a>.</em></p>
<hr />
<h2 id="requirements"><a class="toclink" href="#requirements">Requirements</a></h2>
<p>REST framework requires the following:</p>
<ul>
<li>Python (3.6, 3.7, 3.8, 3.9, 3.10)</li>
<li>Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1)</li>
<li>Python (3.6, 3.7, 3.8, 3.9, 3.10, 3.11)</li>
<li>Django (3.0, 3.1, 3.2, 4.0, 4.1, 4.2)</li>
</ul>
<p>We <strong>highly recommend</strong> and only officially support the latest patch release of
each Python and Django series.</p>
@ -646,7 +643,7 @@ urlpatterns = [
the repository, run the test suite and contribute changes back to REST
Framework.</p>
<h2 id="support"><a class="toclink" href="#support">Support</a></h2>
<p>For support please see the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, try the <code>#restframework</code> channel on <code>irc.libera.chat</code>, or raise a question on <a href="https://stackoverflow.com/">Stack Overflow</a>, making sure to include the <a href="https://stackoverflow.com/questions/tagged/django-rest-framework">'django-rest-framework'</a> tag.</p>
<p>For support please see the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, try the <code>#restframework</code> channel on <code>irc.libera.chat</code>, or raise a question on <a href="https://stackoverflow.com/">Stack Overflow</a>, making sure to include the <a href="https://stackoverflow.com/questions/tagged/django-rest-framework">'django-rest-framework'</a> tag.</p>
<p>For priority support please sign up for a <a href="https://fund.django-rest-framework.org/topics/funding/">professional or premium sponsorship plan</a>.</p>
<h2 id="security"><a class="toclink" href="#security">Security</a></h2>
<p>Security issues are handled under the supervision of the <a href="https://www.djangoproject.com/foundation/teams/#security-team">Django security team</a>.</p>

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>
@ -461,7 +457,7 @@
<li>Ensure that any 'unsafe' HTTP operations, such as <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code>, always require a valid CSRF token.</li>
</ol>
<p>If you're using <code>SessionAuthentication</code> you'll need to include valid CSRF tokens for any <code>POST</code>, <code>PUT</code>, <code>PATCH</code> or <code>DELETE</code> operations.</p>
<p>In order to make AJAX requests, you need to include CSRF token in the HTTP header, as <a href="https://docs.djangoproject.com/en/stable/ref/csrf/#ajax">described in the Django documentation</a>.</p>
<p>In order to make AJAX requests, you need to include CSRF token in the HTTP header, as <a href="https://docs.djangoproject.com/en/stable/howto/csrf/#using-csrf-protection-with-ajax">described in the Django documentation</a>.</p>
<h2 id="cors"><a class="toclink" href="#cors">CORS</a></h2>
<p><a href="https://www.w3.org/TR/cors/">Cross-Origin Resource Sharing</a> is a mechanism for allowing clients to interact with APIs that are hosted on a different domain. CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.</p>
<p>The best way to deal with CORS in REST framework is to add the required response headers in middleware. This ensures that CORS is supported transparently, without having to change any behavior in your views.</p>

View File

@ -1,973 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>API Clients - Django REST framework</title>
<link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="https://www.django-rest-framework.org/topics/api-clients/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST, API Clients">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="../../css/prettify.css" rel="stylesheet">
<link href="../../css/bootstrap.css" rel="stylesheet">
<link href="../../css/bootstrap-responsive.css" rel="stylesheet">
<link href="../../css/default.css" rel="stylesheet">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#sidebarInclude img {
margin-bottom: 10px;
}
#sidebarInclude a.promo {
color: black;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
</style>
</head>
<body onload="prettyPrint()" class="-page">
<div class="wrapper">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../internationalization/">
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../documenting-your-api/">
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://www.django-rest-framework.org/">Django REST framework</a>
<div class="nav-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav">
<li >
<a href="../..">Home</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../tutorial/quickstart/">Quickstart</a>
</li>
<li >
<a href="../../tutorial/1-serialization/">1 - Serialization</a>
</li>
<li >
<a href="../../tutorial/2-requests-and-responses/">2 - Requests and responses</a>
</li>
<li >
<a href="../../tutorial/3-class-based-views/">3 - Class based views</a>
</li>
<li >
<a href="../../tutorial/4-authentication-and-permissions/">4 - Authentication and permissions</a>
</li>
<li >
<a href="../../tutorial/5-relationships-and-hyperlinked-apis/">5 - Relationships and hyperlinked APIs</a>
</li>
<li >
<a href="../../tutorial/6-viewsets-and-routers/">6 - Viewsets and routers</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../api-guide/requests/">Requests</a>
</li>
<li >
<a href="../../api-guide/responses/">Responses</a>
</li>
<li >
<a href="../../api-guide/views/">Views</a>
</li>
<li >
<a href="../../api-guide/generic-views/">Generic views</a>
</li>
<li >
<a href="../../api-guide/viewsets/">Viewsets</a>
</li>
<li >
<a href="../../api-guide/routers/">Routers</a>
</li>
<li >
<a href="../../api-guide/parsers/">Parsers</a>
</li>
<li >
<a href="../../api-guide/renderers/">Renderers</a>
</li>
<li >
<a href="../../api-guide/serializers/">Serializers</a>
</li>
<li >
<a href="../../api-guide/fields/">Serializer fields</a>
</li>
<li >
<a href="../../api-guide/relations/">Serializer relations</a>
</li>
<li >
<a href="../../api-guide/validators/">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication/">Authentication</a>
</li>
<li >
<a href="../../api-guide/permissions/">Permissions</a>
</li>
<li >
<a href="../../api-guide/caching/">Caching</a>
</li>
<li >
<a href="../../api-guide/throttling/">Throttling</a>
</li>
<li >
<a href="../../api-guide/filtering/">Filtering</a>
</li>
<li >
<a href="../../api-guide/pagination/">Pagination</a>
</li>
<li >
<a href="../../api-guide/versioning/">Versioning</a>
</li>
<li >
<a href="../../api-guide/content-negotiation/">Content negotiation</a>
</li>
<li >
<a href="../../api-guide/metadata/">Metadata</a>
</li>
<li >
<a href="../../api-guide/schemas/">Schemas</a>
</li>
<li >
<a href="../../api-guide/format-suffixes/">Format suffixes</a>
</li>
<li >
<a href="../../api-guide/reverse/">Returning URLs</a>
</li>
<li >
<a href="../../api-guide/exceptions/">Exceptions</a>
</li>
<li >
<a href="../../api-guide/status-codes/">Status codes</a>
</li>
<li >
<a href="../../api-guide/testing/">Testing</a>
</li>
<li >
<a href="../../api-guide/settings/">Settings</a>
</li>
</ul>
</li>
<li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li class="active" >
<a href="./">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>
<li >
<a href="../ajax-csrf-cors/">AJAX, CSRF & CORS</a>
</li>
<li >
<a href="../html-and-forms/">HTML & Forms</a>
</li>
<li >
<a href="../browser-enhancements/">Browser Enhancements</a>
</li>
<li >
<a href="../browsable-api/">The Browsable API</a>
</li>
<li >
<a href="../rest-hypermedia-hateoas/">REST, Hypermedia & HATEOAS</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
<ul class="dropdown-menu">
<li >
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
</li>
<li >
<a href="../../community/third-party-packages/">Third Party Packages</a>
</li>
<li >
<a href="../../community/contributing/">Contributing to REST framework</a>
</li>
<li >
<a href="../../community/project-management/">Project management</a>
</li>
<li >
<a href="../../community/release-notes/">Release Notes</a>
</li>
<li >
<a href="../../community/3.14-announcement/">3.14 Announcement</a>
</li>
<li >
<a href="../../community/3.13-announcement/">3.13 Announcement</a>
</li>
<li >
<a href="../../community/3.12-announcement/">3.12 Announcement</a>
</li>
<li >
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
</li>
<li >
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
</li>
<li >
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
</li>
<li >
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
</li>
<li >
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
</li>
<li >
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
</li>
<li >
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
</li>
<li >
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
</li>
<li >
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
</li>
<li >
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
</li>
<li >
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
</li>
<li >
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
</li>
<li >
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
</li>
<li >
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
</li>
<li >
<a href="../../community/funding/">Funding</a>
</li>
<li >
<a href="../../community/jobs/">Jobs</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<div class="body-content">
<div class="container-fluid">
<!-- Search Modal -->
<div id="mkdocs_search_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="myModalLabel">Documentation search</h3>
</div>
<div class="modal-body">
<form role="form" autocomplete="off">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
</div>
</form>
<div id="mkdocs-search-results"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main">
<a href="#api-clients">API Clients</a>
</li>
<li>
<a href="#client-side-core-api">Client-side Core API</a>
</li>
<li class="main">
<a href="#command-line-client">Command line client</a>
</li>
<li>
<a href="#getting-started">Getting started</a>
</li>
<li>
<a href="#authentication-headers">Authentication &amp; headers</a>
</li>
<li>
<a href="#codecs">Codecs</a>
</li>
<li>
<a href="#utilities">Utilities</a>
</li>
<li>
<a href="#other-commands">Other commands</a>
</li>
<li class="main">
<a href="#python-client-library">Python client library</a>
</li>
<li>
<a href="#getting-started_1">Getting started</a>
</li>
<li>
<a href="#authentication">Authentication</a>
</li>
<li>
<a href="#interacting-with-the-api">Interacting with the API</a>
</li>
<li>
<a href="#codecs_1">Codecs</a>
</li>
<li>
<a href="#transports">Transports</a>
</li>
<li class="main">
<a href="#javascript-client-library">JavaScript Client Library</a>
</li>
<li>
<a href="#installing-the-javascript-client">Installing the JavaScript client</a>
</li>
<li>
<a href="#instantiating-a-client">Instantiating a client</a>
</li>
<li>
<a href="#using-the-client">Using the client</a>
</li>
<li>
<a href="#installation-with-node">Installation with node</a>
</li>
<div class="promo">
<hr/>
<div id="sidebarInclude">
</div>
</ul>
</div>
</div>
<div id="main-content" class="span9">
<h1 id="api-clients"><a class="toclink" href="#api-clients">API Clients</a></h1>
<p>An API client handles the underlying details of how network requests are made
and how responses are decoded. They present the developer with an application
interface to work against, rather than working directly with the network interface.</p>
<p>The API clients documented here are not restricted to APIs built with Django REST framework.
They can be used with any API that exposes a supported schema format.</p>
<p>For example, <a href="https://devcenter.heroku.com/categories/platform-api">the Heroku platform API</a> exposes a schema in the JSON
Hyperschema format. As a result, the Core API command line client and Python
client library can be <a href="https://www.coreapi.org/tools-and-resources/example-services/#heroku-json-hyper-schema">used to interact with the Heroku API</a>.</p>
<h2 id="client-side-core-api"><a class="toclink" href="#client-side-core-api">Client-side Core API</a></h2>
<p><a href="https://www.coreapi.org/">Core API</a> is a document specification that can be used to describe APIs. It can
be used either server-side, as is done with REST framework's <a href="../../api-guide/schemas/">schema generation</a>,
or used client-side, as described here.</p>
<p>When used client-side, Core API allows for <em>dynamically driven client libraries</em>
that can interact with any API that exposes a supported schema or hypermedia
format.</p>
<p>Using a dynamically driven client has a number of advantages over interacting
with an API by building HTTP requests directly.</p>
<h4 id="more-meaningful-interaction"><a class="toclink" href="#more-meaningful-interaction">More meaningful interaction</a></h4>
<p>API interactions are presented in a more meaningful way. You're working at
the application interface layer, rather than the network interface layer.</p>
<h4 id="resilience-evolvability"><a class="toclink" href="#resilience-evolvability">Resilience &amp; evolvability</a></h4>
<p>The client determines what endpoints are available, what parameters exist
against each particular endpoint, and how HTTP requests are formed.</p>
<p>This also allows for a degree of API evolvability. URLs can be modified
without breaking existing clients, or more efficient encodings can be used
on-the-wire, with clients transparently upgrading.</p>
<h4 id="self-descriptive-apis"><a class="toclink" href="#self-descriptive-apis">Self-descriptive APIs</a></h4>
<p>A dynamically driven client is able to present documentation on the API to the
end user. This documentation allows the user to discover the available endpoints
and parameters, and better understand the API they are working with.</p>
<p>Because this documentation is driven by the API schema it will always be fully
up to date with the most recently deployed version of the service.</p>
<hr />
<h1 id="command-line-client"><a class="toclink" href="#command-line-client">Command line client</a></h1>
<p>The command line client allows you to inspect and interact with any API that
exposes a supported schema format.</p>
<h2 id="getting-started"><a class="toclink" href="#getting-started">Getting started</a></h2>
<p>To install the Core API command line client, use <code>pip</code>.</p>
<p>Note that the command-line client is a separate package to the
python client library. Make sure to install <code>coreapi-cli</code>.</p>
<pre><code>$ pip install coreapi-cli
</code></pre>
<p>To start inspecting and interacting with an API the schema must first be loaded
from the network.</p>
<pre><code>$ coreapi get http://api.example.org/
&lt;Pastebin API "http://127.0.0.1:8000/"&gt;
snippets: {
create(code, [title], [linenos], [language], [style])
destroy(pk)
highlight(pk)
list([page])
partial_update(pk, [title], [code], [linenos], [language], [style])
retrieve(pk)
update(pk, code, [title], [linenos], [language], [style])
}
users: {
list([page])
retrieve(pk)
}
</code></pre>
<p>This will then load the schema, displaying the resulting <code>Document</code>. This
<code>Document</code> includes all the available interactions that may be made against the API.</p>
<p>To interact with the API, use the <code>action</code> command. This command requires a list
of keys that are used to index into the link.</p>
<pre><code>$ coreapi action users list
[
{
"url": "http://127.0.0.1:8000/users/2/",
"id": 2,
"username": "aziz",
"snippets": []
},
...
]
</code></pre>
<p>To inspect the underlying HTTP request and response, use the <code>--debug</code> flag.</p>
<pre><code>$ coreapi action users list --debug
&gt; GET /users/ HTTP/1.1
&gt; Accept: application/vnd.coreapi+json, */*
&gt; Authorization: Basic bWF4Om1heA==
&gt; Host: 127.0.0.1
&gt; User-Agent: coreapi
&lt; 200 OK
&lt; Allow: GET, HEAD, OPTIONS
&lt; Content-Type: application/json
&lt; Date: Thu, 30 Jun 2016 10:51:46 GMT
&lt; Server: WSGIServer/0.1 Python/2.7.10
&lt; Vary: Accept, Cookie
&lt;
&lt; [{"url":"http://127.0.0.1/users/2/","id":2,"username":"aziz","snippets":[]},{"url":"http://127.0.0.1/users/3/","id":3,"username":"amy","snippets":["http://127.0.0.1/snippets/3/"]},{"url":"http://127.0.0.1/users/4/","id":4,"username":"max","snippets":["http://127.0.0.1/snippets/4/","http://127.0.0.1/snippets/5/","http://127.0.0.1/snippets/6/","http://127.0.0.1/snippets/7/"]},{"url":"http://127.0.0.1/users/5/","id":5,"username":"jose","snippets":[]},{"url":"http://127.0.0.1/users/6/","id":6,"username":"admin","snippets":["http://127.0.0.1/snippets/1/","http://127.0.0.1/snippets/2/"]}]
[
...
]
</code></pre>
<p>Some actions may include optional or required parameters.</p>
<pre><code>$ coreapi action users create --param username=example
</code></pre>
<p>When using <code>--param</code>, the type of the input will be determined automatically.</p>
<p>If you want to be more explicit about the parameter type then use <code>--data</code> for
any null, numeric, boolean, list, or object inputs, and use <code>--string</code> for string inputs.</p>
<pre><code>$ coreapi action users edit --string username=tomchristie --data is_admin=true
</code></pre>
<h2 id="authentication-headers"><a class="toclink" href="#authentication-headers">Authentication &amp; headers</a></h2>
<p>The <code>credentials</code> command is used to manage the request <code>Authentication:</code> header.
Any credentials added are always linked to a particular domain, so as to ensure
that credentials are not leaked across differing APIs.</p>
<p>The format for adding a new credential is:</p>
<pre><code>$ coreapi credentials add &lt;domain&gt; &lt;credentials string&gt;
</code></pre>
<p>For instance:</p>
<pre><code>$ coreapi credentials add api.example.org "Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
</code></pre>
<p>The optional <code>--auth</code> flag also allows you to add specific types of authentication,
handling the encoding for you. Currently only <code>"basic"</code> is supported as an option here.
For example:</p>
<pre><code>$ coreapi credentials add api.example.org tomchristie:foobar --auth basic
</code></pre>
<p>You can also add specific request headers, using the <code>headers</code> command:</p>
<pre><code>$ coreapi headers add api.example.org x-api-version 2
</code></pre>
<p>For more information and a listing of the available subcommands use <code>coreapi
credentials --help</code> or <code>coreapi headers --help</code>.</p>
<h2 id="codecs"><a class="toclink" href="#codecs">Codecs</a></h2>
<p>By default the command line client only includes support for reading Core JSON
schemas, however it includes a plugin system for installing additional codecs.</p>
<pre><code>$ pip install openapi-codec jsonhyperschema-codec hal-codec
$ coreapi codecs show
Codecs
corejson application/vnd.coreapi+json encoding, decoding
hal application/hal+json encoding, decoding
openapi application/openapi+json encoding, decoding
jsonhyperschema application/schema+json decoding
json application/json data
text text/* data
</code></pre>
<h2 id="utilities"><a class="toclink" href="#utilities">Utilities</a></h2>
<p>The command line client includes functionality for bookmarking API URLs
under a memorable name. For example, you can add a bookmark for the
existing API, like so...</p>
<pre><code>$ coreapi bookmarks add accountmanagement
</code></pre>
<p>There is also functionality for navigating forward or backward through the
history of which API URLs have been accessed.</p>
<pre><code>$ coreapi history show
$ coreapi history back
</code></pre>
<p>For more information and a listing of the available subcommands use
<code>coreapi bookmarks --help</code> or <code>coreapi history --help</code>.</p>
<h2 id="other-commands"><a class="toclink" href="#other-commands">Other commands</a></h2>
<p>To display the current <code>Document</code>:</p>
<pre><code>$ coreapi show
</code></pre>
<p>To reload the current <code>Document</code> from the network:</p>
<pre><code>$ coreapi reload
</code></pre>
<p>To load a schema file from disk:</p>
<pre><code>$ coreapi load my-api-schema.json --format corejson
</code></pre>
<p>To dump the current document to console in a given format:</p>
<pre><code>$ coreapi dump --format openapi
</code></pre>
<p>To remove the current document, along with all currently saved history,
credentials, headers and bookmarks:</p>
<pre><code>$ coreapi clear
</code></pre>
<hr />
<h1 id="python-client-library"><a class="toclink" href="#python-client-library">Python client library</a></h1>
<p>The <code>coreapi</code> Python package allows you to programmatically interact with any
API that exposes a supported schema format.</p>
<h2 id="getting-started_1"><a class="toclink" href="#getting-started_1">Getting started</a></h2>
<p>You'll need to install the <code>coreapi</code> package using <code>pip</code> before you can get
started.</p>
<pre><code>$ pip install coreapi
</code></pre>
<p>In order to start working with an API, we first need a <code>Client</code> instance. The
client holds any configuration around which codecs and transports are supported
when interacting with an API, which allows you to provide for more advanced
kinds of behaviour.</p>
<pre><code>import coreapi
client = coreapi.Client()
</code></pre>
<p>Once we have a <code>Client</code> instance, we can fetch an API schema from the network.</p>
<pre><code>schema = client.get('https://api.example.org/')
</code></pre>
<p>The object returned from this call will be a <code>Document</code> instance, which is
a representation of the API schema.</p>
<h2 id="authentication"><a class="toclink" href="#authentication">Authentication</a></h2>
<p>Typically you'll also want to provide some authentication credentials when
instantiating the client.</p>
<h4 id="token-authentication"><a class="toclink" href="#token-authentication">Token authentication</a></h4>
<p>The <code>TokenAuthentication</code> class can be used to support REST framework's built-in
<code>TokenAuthentication</code>, as well as OAuth and JWT schemes.</p>
<pre><code>auth = coreapi.auth.TokenAuthentication(
scheme='JWT',
token='&lt;token&gt;'
)
client = coreapi.Client(auth=auth)
</code></pre>
<p>When using TokenAuthentication you'll probably need to implement a login flow
using the CoreAPI client.</p>
<p>A suggested pattern for this would be to initially make an unauthenticated client
request to an "obtain token" endpoint</p>
<p>For example, using the "Django REST framework JWT" package</p>
<pre><code>client = coreapi.Client()
schema = client.get('https://api.example.org/')
action = ['api-token-auth', 'create']
params = {"username": "example", "password": "secret"}
result = client.action(schema, action, params)
auth = coreapi.auth.TokenAuthentication(
scheme='JWT',
token=result['token']
)
client = coreapi.Client(auth=auth)
</code></pre>
<h4 id="basic-authentication"><a class="toclink" href="#basic-authentication">Basic authentication</a></h4>
<p>The <code>BasicAuthentication</code> class can be used to support HTTP Basic Authentication.</p>
<pre><code>auth = coreapi.auth.BasicAuthentication(
username='&lt;username&gt;',
password='&lt;password&gt;'
)
client = coreapi.Client(auth=auth)
</code></pre>
<h2 id="interacting-with-the-api"><a class="toclink" href="#interacting-with-the-api">Interacting with the API</a></h2>
<p>Now that we have a client and have fetched our schema <code>Document</code>, we can now
start to interact with the API:</p>
<pre><code>users = client.action(schema, ['users', 'list'])
</code></pre>
<p>Some endpoints may include named parameters, which might be either optional or required:</p>
<pre><code>new_user = client.action(schema, ['users', 'create'], params={"username": "max"})
</code></pre>
<h2 id="codecs_1"><a class="toclink" href="#codecs_1">Codecs</a></h2>
<p>Codecs are responsible for encoding or decoding Documents.</p>
<p>The decoding process is used by a client to take a bytestring of an API schema
definition, and returning the Core API <code>Document</code> that represents that interface.</p>
<p>A codec should be associated with a particular media type, such as <code>'application/coreapi+json'</code>.</p>
<p>This media type is used by the server in the response <code>Content-Type</code> header,
in order to indicate what kind of data is being returned in the response.</p>
<h4 id="configuring-codecs"><a class="toclink" href="#configuring-codecs">Configuring codecs</a></h4>
<p>The codecs that are available can be configured when instantiating a client.
The keyword argument used here is <code>decoders</code>, because in the context of a
client the codecs are only for <em>decoding</em> responses.</p>
<p>In the following example we'll configure a client to only accept <code>Core JSON</code>
and <code>JSON</code> responses. This will allow us to receive and decode a Core JSON schema,
and subsequently to receive JSON responses made against the API.</p>
<pre><code>from coreapi import codecs, Client
decoders = [codecs.CoreJSONCodec(), codecs.JSONCodec()]
client = Client(decoders=decoders)
</code></pre>
<h4 id="loading-and-saving-schemas"><a class="toclink" href="#loading-and-saving-schemas">Loading and saving schemas</a></h4>
<p>You can use a codec directly, in order to load an existing schema definition,
and return the resulting <code>Document</code>.</p>
<pre><code>input_file = open('my-api-schema.json', 'rb')
schema_definition = input_file.read()
codec = codecs.CoreJSONCodec()
schema = codec.load(schema_definition)
</code></pre>
<p>You can also use a codec directly to generate a schema definition given a <code>Document</code> instance:</p>
<pre><code>schema_definition = codec.dump(schema)
output_file = open('my-api-schema.json', 'rb')
output_file.write(schema_definition)
</code></pre>
<h2 id="transports"><a class="toclink" href="#transports">Transports</a></h2>
<p>Transports are responsible for making network requests. The set of transports
that a client has installed determines which network protocols it is able to
support.</p>
<p>Currently the <code>coreapi</code> library only includes an HTTP/HTTPS transport, but
other protocols can also be supported.</p>
<h4 id="configuring-transports"><a class="toclink" href="#configuring-transports">Configuring transports</a></h4>
<p>The behavior of the network layer can be customized by configuring the
transports that the client is instantiated with.</p>
<pre><code>import requests
from coreapi import transports, Client
credentials = {'api.example.org': 'Token 3bd44a009d16ff'}
transports = transports.HTTPTransport(credentials=credentials)
client = Client(transports=transports)
</code></pre>
<p>More complex customizations can also be achieved, for example modifying the
underlying <code>requests.Session</code> instance to <a href="http://docs.python-requests.org/en/master/user/advanced/#transport-adapters">attach transport adaptors</a>
that modify the outgoing requests.</p>
<hr />
<h1 id="javascript-client-library"><a class="toclink" href="#javascript-client-library">JavaScript Client Library</a></h1>
<p>The JavaScript client library allows you to interact with your API either from a browser, or using node.</p>
<h2 id="installing-the-javascript-client"><a class="toclink" href="#installing-the-javascript-client">Installing the JavaScript client</a></h2>
<p>There are two separate JavaScript resources that you need to include in your HTML pages in order to use the JavaScript client library. These are a static <code>coreapi.js</code> file, which contains the code for the dynamic client library, and a templated <code>schema.js</code> resource, which exposes your API schema.</p>
<p>First, install the API documentation views. These will include the schema resource that'll allow you to load the schema directly from an HTML page, without having to make an asynchronous AJAX call.</p>
<pre><code>from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
path('docs/', include_docs_urls(title='My API service'), name='api-docs'),
]
</code></pre>
<p>Once the API documentation URLs are installed, you'll be able to include both the required JavaScript resources. Note that the ordering of these two lines is important, as the schema loading requires CoreAPI to already be installed.</p>
<pre><code>&lt;!--
Load the CoreAPI library and the API schema.
/static/rest_framework/js/coreapi-0.1.1.js
/docs/schema.js
--&gt;
{% load static %}
&lt;script src="{% static 'rest_framework/js/coreapi-0.1.1.js' %}"&gt;&lt;/script&gt;
&lt;script src="{% url 'api-docs:schema-js' %}"&gt;&lt;/script&gt;
</code></pre>
<p>The <code>coreapi</code> library, and the <code>schema</code> object will now both be available on the <code>window</code> instance.</p>
<pre><code>const coreapi = window.coreapi;
const schema = window.schema;
</code></pre>
<h2 id="instantiating-a-client"><a class="toclink" href="#instantiating-a-client">Instantiating a client</a></h2>
<p>In order to interact with the API you'll need a client instance.</p>
<pre><code>var client = new coreapi.Client();
</code></pre>
<p>Typically you'll also want to provide some authentication credentials when
instantiating the client.</p>
<h4 id="session-authentication"><a class="toclink" href="#session-authentication">Session authentication</a></h4>
<p>The <code>SessionAuthentication</code> class allows session cookies to provide the user
authentication. You'll want to provide a standard HTML login flow, to allow
the user to login, and then instantiate a client using session authentication:</p>
<pre><code>let auth = new coreapi.auth.SessionAuthentication({
csrfCookieName: 'csrftoken',
csrfHeaderName: 'X-CSRFToken',
});
let client = new coreapi.Client({auth: auth});
</code></pre>
<p>The authentication scheme will handle including a CSRF header in any outgoing
requests for unsafe HTTP methods.</p>
<h4 id="token-authentication_1"><a class="toclink" href="#token-authentication_1">Token authentication</a></h4>
<p>The <code>TokenAuthentication</code> class can be used to support REST framework's built-in
<code>TokenAuthentication</code>, as well as OAuth and JWT schemes.</p>
<pre><code>let auth = new coreapi.auth.TokenAuthentication({
scheme: 'JWT',
token: '&lt;token&gt;',
});
let client = new coreapi.Client({auth: auth});
</code></pre>
<p>When using TokenAuthentication you'll probably need to implement a login flow
using the CoreAPI client.</p>
<p>A suggested pattern for this would be to initially make an unauthenticated client
request to an "obtain token" endpoint</p>
<p>For example, using the "Django REST framework JWT" package</p>
<pre><code>// Setup some globally accessible state
window.client = new coreapi.Client();
window.loggedIn = false;
function loginUser(username, password) {
let action = ["api-token-auth", "obtain-token"];
let params = {username: username, password: password};
client.action(schema, action, params).then(function(result) {
// On success, instantiate an authenticated client.
let auth = window.coreapi.auth.TokenAuthentication({
scheme: 'JWT',
token: result['token'],
})
window.client = coreapi.Client({auth: auth});
window.loggedIn = true;
}).catch(function (error) {
// Handle error case where eg. user provides incorrect credentials.
})
}
</code></pre>
<h4 id="basic-authentication_1"><a class="toclink" href="#basic-authentication_1">Basic authentication</a></h4>
<p>The <code>BasicAuthentication</code> class can be used to support HTTP Basic Authentication.</p>
<pre><code>let auth = new coreapi.auth.BasicAuthentication({
username: '&lt;username&gt;',
password: '&lt;password&gt;',
})
let client = new coreapi.Client({auth: auth});
</code></pre>
<h2 id="using-the-client"><a class="toclink" href="#using-the-client">Using the client</a></h2>
<p>Making requests:</p>
<pre><code>let action = ["users", "list"];
client.action(schema, action).then(function(result) {
// Return value is in 'result'
})
</code></pre>
<p>Including parameters:</p>
<pre><code>let action = ["users", "create"];
let params = {username: "example", email: "example@example.com"};
client.action(schema, action, params).then(function(result) {
// Return value is in 'result'
})
</code></pre>
<p>Handling errors:</p>
<pre><code>client.action(schema, action, params).then(function(result) {
// Return value is in 'result'
}).catch(function (error) {
// Error value is in 'error'
})
</code></pre>
<h2 id="installation-with-node"><a class="toclink" href="#installation-with-node">Installation with node</a></h2>
<p>The coreapi package is available on NPM.</p>
<pre><code>$ npm install coreapi
$ node
const coreapi = require('coreapi')
</code></pre>
<p>You'll either want to include the API schema in your codebase directly, by copying it from the <code>schema.js</code> resource, or else load the schema asynchronously. For example:</p>
<pre><code>let client = new coreapi.Client();
let schema = null;
client.get("https://api.example.org/").then(function(data) {
// Load a CoreJSON API schema.
schema = data;
console.log('schema loaded');
})
</code></pre>
</div> <!--/span-->
</div> <!--/row-->
</div> <!--/.fluid-container-->
</div> <!--/.body content-->
<div id="push"></div>
</div> <!--/.wrapper -->
<footer class="span12">
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
</p>
</footer>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
<script src="../../js/jquery-1.8.1-min.js"></script>
<script src="../../js/prettify-1.0.js"></script>
<script src="../../js/bootstrap-2.1.1-min.js"></script>
<script src="../../js/theme.js"></script>
<script>var base_url = '../..';</script>
<script src="../../search/main.js" defer></script>
<script>
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav/dropdown to no higher than browser window
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
});
});
</script>
</body>
</html>

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>
@ -455,7 +451,7 @@
<h2 id="formats"><a class="toclink" href="#formats">Formats</a></h2>
<p>By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using <code>?format=</code> in the request, so you can look at the raw JSON response in a browser by adding <code>?format=json</code> to the URL. There are helpful extensions for viewing JSON in <a href="https://addons.mozilla.org/en-US/firefox/addon/jsonview/">Firefox</a> and <a href="https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc">Chrome</a>.</p>
<h2 id="customizing"><a class="toclink" href="#customizing">Customizing</a></h2>
<p>The browsable API is built with <a href="https://getbootstrap.com/">Twitter's Bootstrap</a> (v 3.3.5), making it easy to customize the look-and-feel.</p>
<p>The browsable API is built with <a href="https://getbootstrap.com/">Twitter's Bootstrap</a> (v 3.4.1), making it easy to customize the look-and-feel.</p>
<p>To customize the default style, create a template called <code>rest_framework/api.html</code> that extends from <code>rest_framework/base.html</code>. For example:</p>
<p><strong>templates/rest_framework/api.html</strong></p>
<pre><code>{% extends "rest_framework/base.html" %}
@ -468,13 +464,13 @@
&lt;link rel="stylesheet" href="/path/to/my/bootstrap.css" type="text/css"&gt;
{% endblock %}
</code></pre>
<p>Suitable pre-made replacement themes are available at <a href="https://bootswatch.com/">Bootswatch</a>. To use any of the Bootswatch themes, simply download the theme's <code>bootstrap.min.css</code> file, add it to your project, and replace the default one as described above.</p>
<p>Suitable pre-made replacement themes are available at <a href="https://bootswatch.com/">Bootswatch</a>. To use any of the Bootswatch themes, simply download the theme's <code>bootstrap.min.css</code> file, add it to your project, and replace the default one as described above. Make sure that the Bootstrap version of the new theme matches that of the default theme.</p>
<p>You can also change the navbar variant, which by default is <code>navbar-inverse</code>, using the <code>bootstrap_navbar_variant</code> block. The empty <code>{% block bootstrap_navbar_variant %}{% endblock %}</code> will use the original Bootstrap navbar style.</p>
<p>Full example:</p>
<pre><code>{% extends "rest_framework/base.html" %}
{% block bootstrap_theme %}
&lt;link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.min.css" type="text/css"&gt;
&lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@3.4.1/flatly/bootstrap.min.css" type="text/css"&gt;
{% endblock %}
{% block bootstrap_navbar_variant %}{% endblock %}

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>

View File

@ -54,7 +54,7 @@
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../api-clients/">
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../internationalization/">
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../../api-guide/settings/">
@ -238,10 +238,6 @@
<a href="./">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>
@ -418,11 +414,11 @@
<li>
<a href="#generating-documentation-from-openapi-schemas">Generating documentation from OpenAPI schemas</a>
<a href="#third-party-packages-for-openapi-support">Third party packages for OpenAPI support</a>
</li>
<li>
<a href="#third-party-packages">Third party packages</a>
<a href="#built-in-openapi-schema-generation-deprecated">Built-in OpenAPI schema generation (deprecated)</a>
</li>
<li>
@ -453,10 +449,30 @@
<p>A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state.</p>
<p>&mdash; Roy Fielding, <a href="https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">REST APIs must be hypertext driven</a></p>
</blockquote>
<p>REST framework provides built-in support for generating OpenAPI schemas, which
can be used with tools that allow you to build API documentation.</p>
<p>There are also a number of great third-party documentation packages available.</p>
<h2 id="generating-documentation-from-openapi-schemas"><a class="toclink" href="#generating-documentation-from-openapi-schemas">Generating documentation from OpenAPI schemas</a></h2>
<p>REST framework provides a range of different choices for documenting your API. The following
is a non-exhaustive list of the most popular ones.</p>
<h2 id="third-party-packages-for-openapi-support"><a class="toclink" href="#third-party-packages-for-openapi-support">Third party packages for OpenAPI support</a></h2>
<h3 id="drf-spectacular"><a class="toclink" href="#drf-spectacular">drf-spectacular</a></h3>
<p><a href="https://github.com/tfranzel/drf-spectacular/">drf-spectacular</a> is an <a href="https://openapis.org/">OpenAPI 3</a> schema generation library with explicit
focus on extensibility, customizability and client generation. It is the recommended way for
generating and presenting OpenAPI schemas.</p>
<p>The library aims to extract as much schema information as possible, while providing decorators and extensions for easy
customization. There is explicit support for <a href="https://swagger.io/">swagger-codegen</a>, <a href="https://swagger.io/tools/swagger-ui/">SwaggerUI</a> and <a href="https://github.com/Rebilly/ReDoc">Redoc</a>,
i18n, versioning, authentication, polymorphism (dynamic requests and responses), query/path/header parameters,
documentation and more. Several popular plugins for DRF are supported out-of-the-box as well.</p>
<h3 id="drf-yasg"><a class="toclink" href="#drf-yasg">drf-yasg</a></h3>
<p><a href="https://github.com/axnsan12/drf-yasg/">drf-yasg</a> is a <a href="https://swagger.io/">Swagger / OpenAPI 2</a> generation tool implemented without using the schema generation provided
by Django Rest Framework.</p>
<p>It aims to implement as much of the <a href="https://openapis.org/">OpenAPI 2</a> specification as possible - nested schemas, named models,
response bodies, enum/pattern/min/max validators, form parameters, etc. - and to generate documents usable with code
generation tools like <code>swagger-codegen</code>.</p>
<p>This also translates into a very useful interactive documentation viewer in the form of <code>swagger-ui</code>:</p>
<p><img alt="Screenshot - drf-yasg" src="../../img/drf-yasg.png" /></p>
<hr />
<h2 id="built-in-openapi-schema-generation-deprecated"><a class="toclink" href="#built-in-openapi-schema-generation-deprecated">Built-in OpenAPI schema generation (deprecated)</a></h2>
<p><strong>Deprecation notice: REST framework's built-in support for generating OpenAPI schemas is
deprecated in favor of 3rd party packages that can provide this functionality instead.
As replacement, we recommend using the <a href="#drf-spectacular">drf-spectacular</a> package.</strong></p>
<p>There are a number of packages available that allow you to generate HTML
documentation pages from OpenAPI schemas.</p>
<p>Two popular options are <a href="https://swagger.io/tools/swagger-ui/">Swagger UI</a> and <a href="https://github.com/Rebilly/ReDoc">ReDoc</a>.</p>
@ -503,10 +519,14 @@ urlpatterns = [
# ...
# Route TemplateView to serve Swagger UI template.
# * Provide `extra_context` with view name of `SchemaView`.
path('swagger-ui/', TemplateView.as_view(
template_name='swagger-ui.html',
extra_context={'schema_url':'openapi-schema'}
), name='swagger-ui'),
path(
&quot;swagger-ui/&quot;,
TemplateView.as_view(
template_name=&quot;swagger-ui.html&quot;,
extra_context={&quot;schema_url&quot;: &quot;openapi-schema&quot;},
),
name=&quot;swagger-ui&quot;,
),
]
</code></pre>
<p>See the <a href="https://swagger.io/tools/swagger-ui/">Swagger UI documentation</a> for advanced usage.</p>
@ -544,31 +564,16 @@ urlpatterns = [
# ...
# Route TemplateView to serve the ReDoc template.
# * Provide `extra_context` with view name of `SchemaView`.
path('redoc/', TemplateView.as_view(
template_name='redoc.html',
extra_context={'schema_url':'openapi-schema'}
), name='redoc'),
path(
&quot;redoc/&quot;,
TemplateView.as_view(
template_name=&quot;redoc.html&quot;, extra_context={&quot;schema_url&quot;: &quot;openapi-schema&quot;}
),
name=&quot;redoc&quot;,
),
]
</code></pre>
<p>See the <a href="https://github.com/Rebilly/ReDoc">ReDoc documentation</a> for advanced usage.</p>
<h2 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h2>
<p>There are a number of mature third-party packages for providing API documentation.</p>
<h4 id="drf-yasg-yet-another-swagger-generator"><a class="toclink" href="#drf-yasg-yet-another-swagger-generator">drf-yasg - Yet Another Swagger Generator</a></h4>
<p><a href="https://github.com/axnsan12/drf-yasg/">drf-yasg</a> is a <a href="https://swagger.io/">Swagger</a> generation tool implemented without using the schema generation provided
by Django Rest Framework.</p>
<p>It aims to implement as much of the <a href="https://openapis.org/">OpenAPI</a> specification as possible - nested schemas, named models,
response bodies, enum/pattern/min/max validators, form parameters, etc. - and to generate documents usable with code
generation tools like <code>swagger-codegen</code>.</p>
<p>This also translates into a very useful interactive documentation viewer in the form of <code>swagger-ui</code>:</p>
<p><img alt="Screenshot - drf-yasg" src="../../img/drf-yasg.png" /></p>
<h4 id="drf-spectacular-sane-and-flexible-openapi-30-schema-generation-for-django-rest-framework"><a class="toclink" href="#drf-spectacular-sane-and-flexible-openapi-30-schema-generation-for-django-rest-framework">drf-spectacular - Sane and flexible OpenAPI 3.0 schema generation for Django REST framework</a></h4>
<p><a href="https://github.com/tfranzel/drf-spectacular/">drf-spectacular</a> is a <a href="https://openapis.org/">OpenAPI 3</a> schema generation tool with explicit focus on extensibility,
customizability and client generation. Usage patterns are very similar to <a href="https://github.com/axnsan12/drf-yasg/">drf-yasg</a>.</p>
<p>It aims to extract as much schema information as possible, while providing decorators and extensions for easy
customization. There is explicit support for <a href="https://swagger.io/">swagger-codegen</a>, <a href="https://swagger.io/tools/swagger-ui/">SwaggerUI</a> and <a href="https://github.com/Rebilly/ReDoc">Redoc</a>,
i18n, versioning, authentication, polymorphism (dynamic requests and responses), query/path/header parameters,
documentation and more. Several popular plugins for DRF are supported out-of-the-box as well.</p>
<hr />
<h2 id="self-describing-apis"><a class="toclink" href="#self-describing-apis">Self describing APIs</a></h2>
<p>The browsable API that REST framework provides makes it possible for your API to be entirely self describing. The documentation for each API endpoint can be provided simply by visiting the URL in your browser.</p>
<p><img alt="Screenshot - Self describing API" src="../../img/self-describing.png" /></p>

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>

View File

@ -57,7 +57,7 @@
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../ajax-csrf-cors/">
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../api-clients/">
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../documenting-your-api/">
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li class="active" >
<a href="./">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>
@ -449,7 +445,7 @@
<p>You keep using that word "REST". I do not think it means what you think it means.</p>
<p>&mdash; Mike Amundsen, <a href="https://vimeo.com/channels/restfest/49503453">REST fest 2012 keynote</a>.</p>
</blockquote>
<p>First off, the disclaimer. The name "Django REST framework" was decided back in early 2011 and was chosen simply to sure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".</p>
<p>First off, the disclaimer. The name "Django REST framework" was decided back in early 2011 and was chosen simply to ensure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".</p>
<p>If you are serious about designing a Hypermedia API, you should look to resources outside of this documentation to help inform your design choices.</p>
<p>The following fall into the "required reading" category.</p>
<ul>

View File

@ -238,10 +238,6 @@
<a href="../documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../api-clients/">API Clients</a>
</li>
<li >
<a href="../internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -618,7 +614,7 @@ serializer.data
# [OrderedDict([('id', 1), ('title', ''), ('code', 'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', ''), ('code', 'print("hello, world")\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', ''), ('code', 'print("hello, world")'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
</code></pre>
<h2 id="using-modelserializers"><a class="toclink" href="#using-modelserializers">Using ModelSerializers</a></h2>
<p>Our <code>SnippetSerializer</code> class is replicating a lot of information that's also contained in the <code>Snippet</code> model. It would be nice if we could keep our code a bit more concise.</p>
<p>Our <code>SnippetSerializer</code> class is replicating a lot of information that's also contained in the <code>Snippet</code> model. It would be nice if we could keep our code a bit more concise.</p>
<p>In the same way that Django provides both <code>Form</code> classes and <code>ModelForm</code> classes, REST framework includes both <code>Serializer</code> classes, and <code>ModelSerializer</code> classes.</p>
<p>Let's look at refactoring our serializer using the <code>ModelSerializer</code> class.
Open the file <code>snippets/serializers.py</code> again, and replace the <code>SnippetSerializer</code> class with the following.</p>
@ -729,7 +725,7 @@ urlpatterns = [
Validating models...
0 errors found
Django version 4.0,1 using settings 'tutorial.settings'
Django version 4.0, using settings 'tutorial.settings'
Starting Development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
</code></pre>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -485,7 +481,7 @@ request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' met
<li>The <code>APIView</code> class for working with class-based views.</li>
</ol>
<p>These wrappers provide a few bits of functionality such as making sure you receive <code>Request</code> instances in your view, and adding context to <code>Response</code> objects so that content negotiation can be performed.</p>
<p>The wrappers also provide behaviour such as returning <code>405 Method Not Allowed</code> responses when appropriate, and handling any <code>ParseError</code> exceptions that occur when accessing <code>request.data</code> with malformed input.</p>
<p>The wrappers also provide behavior such as returning <code>405 Method Not Allowed</code> responses when appropriate, and handling any <code>ParseError</code> exceptions that occur when accessing <code>request.data</code> with malformed input.</p>
<h2 id="pulling-it-all-together"><a class="toclink" href="#pulling-it-all-together">Pulling it all together</a></h2>
<p>Okay, let's go ahead and start using these new components to refactor our views slightly.</p>
<pre><code>from rest_framework import status

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -516,8 +512,8 @@ urlpatterns = format_suffix_patterns(urlpatterns)
</code></pre>
<p>Okay, we're done. If you run the development server everything should be working just as before.</p>
<h2 id="using-mixins"><a class="toclink" href="#using-mixins">Using mixins</a></h2>
<p>One of the big wins of using class-based views is that it allows us to easily compose reusable bits of behaviour.</p>
<p>The create/retrieve/update/delete operations that we've been using so far are going to be pretty similar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.</p>
<p>One of the big wins of using class-based views is that it allows us to easily compose reusable bits of behavior.</p>
<p>The create/retrieve/update/delete operations that we've been using so far are going to be pretty similar for any model-backed API views we create. Those bits of common behavior are implemented in REST framework's mixin classes.</p>
<p>Let's take a look at how we can compose the views by using the mixin classes. Here's our <code>views.py</code> module again.</p>
<pre><code>from snippets.models import Snippet
from snippets.serializers import SnippetSerializer

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -430,7 +426,7 @@
</li>
<li>
<a href="#trade-offs-between-views-vs-viewsets">Trade-offs between views vs viewsets</a>
<a href="#trade-offs-between-views-vs-viewsets">Trade-offs between views vs ViewSets</a>
</li>
@ -454,9 +450,10 @@
<p>A <code>ViewSet</code> class is only bound to a set of method handlers at the last moment, when it is instantiated into a set of views, typically by using a <code>Router</code> class which handles the complexities of defining the URL conf for you.</p>
<h2 id="refactoring-to-use-viewsets"><a class="toclink" href="#refactoring-to-use-viewsets">Refactoring to use ViewSets</a></h2>
<p>Let's take our current set of views, and refactor them into view sets.</p>
<p>First of all let's refactor our <code>UserList</code> and <code>UserDetail</code> views into a single <code>UserViewSet</code>. We can remove the two views, and replace them with a single class:</p>
<p>First of all let's refactor our <code>UserList</code> and <code>UserDetail</code> classes into a single <code>UserViewSet</code> class. We can remove the two view classes, and replace them with a single ViewSet class:</p>
<pre><code>from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
This viewset automatically provides `list` and `retrieve` actions.
@ -466,13 +463,15 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
</code></pre>
<p>Here we've used the <code>ReadOnlyModelViewSet</code> class to automatically provide the default 'read-only' operations. We're still setting the <code>queryset</code> and <code>serializer_class</code> attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.</p>
<p>Next we're going to replace the <code>SnippetList</code>, <code>SnippetDetail</code> and <code>SnippetHighlight</code> view classes. We can remove the three views, and again replace them with a single class.</p>
<pre><code>from rest_framework.decorators import action
<pre><code>from rest_framework import permissions
from rest_framework import renderers
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions
class SnippetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
This ViewSet automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
@ -498,8 +497,9 @@ class SnippetViewSet(viewsets.ModelViewSet):
<p>The handler methods only get bound to the actions when we define the URLConf.
To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.</p>
<p>In the <code>snippets/urls.py</code> file we bind our <code>ViewSet</code> classes into a set of concrete views.</p>
<pre><code>from snippets.views import SnippetViewSet, UserViewSet, api_root
from rest_framework import renderers
<pre><code>from rest_framework import renderers
from snippets.views import api_root, SnippetViewSet, UserViewSet
snippet_list = SnippetViewSet.as_view({
'get': 'list',
@ -521,7 +521,7 @@ user_detail = UserViewSet.as_view({
'get': 'retrieve'
})
</code></pre>
<p>Notice how we're creating multiple views from each <code>ViewSet</code> class, by binding the http methods to the required action for each view.</p>
<p>Notice how we're creating multiple views from each <code>ViewSet</code> class, by binding the HTTP methods to the required action for each view.</p>
<p>Now that we've bound our resources into concrete views, we can register the views with the URL conf as usual.</p>
<pre><code>urlpatterns = format_suffix_patterns([
path('', api_root),
@ -537,23 +537,24 @@ user_detail = UserViewSet.as_view({
<p>Here's our re-wired <code>snippets/urls.py</code> file.</p>
<pre><code>from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
# Create a router and register our ViewSets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippet")
router.register(r'users', views.UserViewSet,basename="user")
router.register(r'snippets', views.SnippetViewSet, basename='snippet')
router.register(r'users', views.UserViewSet, basename='user')
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
</code></pre>
<p>Registering the viewsets with the router is similar to providing a urlpattern. We include two arguments - the URL prefix for the views, and the viewset itself.</p>
<p>The <code>DefaultRouter</code> class we're using also automatically creates the API root view for us, so we can now delete the <code>api_root</code> method from our <code>views</code> module.</p>
<h2 id="trade-offs-between-views-vs-viewsets"><a class="toclink" href="#trade-offs-between-views-vs-viewsets">Trade-offs between views vs viewsets</a></h2>
<p>Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.</p>
<p>That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.</p>
<p>Registering the ViewSets with the router is similar to providing a urlpattern. We include two arguments - the URL prefix for the views, and the view set itself.</p>
<p>The <code>DefaultRouter</code> class we're using also automatically creates the API root view for us, so we can now delete the <code>api_root</code> function from our <code>views</code> module.</p>
<h2 id="trade-offs-between-views-vs-viewsets"><a class="toclink" href="#trade-offs-between-views-vs-viewsets">Trade-offs between views vs ViewSets</a></h2>
<p>Using ViewSets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.</p>
<p>That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function-based views. Using ViewSets is less explicit than building your API views individually.</p>
</div> <!--/span-->

View File

@ -238,10 +238,6 @@
<a href="../../topics/documenting-your-api/">Documenting your API</a>
</li>
<li >
<a href="../../topics/api-clients/">API Clients</a>
</li>
<li >
<a href="../../topics/internationalization/">Internationalization</a>
</li>
@ -487,34 +483,36 @@ cd ..
&lt;some path&gt;/tutorial
$ find .
.
./manage.py
./tutorial
./tutorial/asgi.py
./tutorial/__init__.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/__init__.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/asgi.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py
./env
./env/...
./manage.py
</code></pre>
<p>It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external modules (a topic that goes outside the scope of the quickstart).</p>
<p>Now sync your database for the first time:</p>
<pre><code>python manage.py migrate
</code></pre>
<p>We'll also create an initial user named <code>admin</code> with a password of <code>password123</code>. We'll authenticate as that user later in our example.</p>
<pre><code>python manage.py createsuperuser --email admin@example.com --username admin
<p>We'll also create an initial user named <code>admin</code> with a password. We'll authenticate as that user later in our example.</p>
<pre><code>python manage.py createsuperuser --username admin --email admin@example.com
</code></pre>
<p>Once you've set up a database and the initial user is created and ready to go, open up the app's directory and we'll get coding...</p>
<h2 id="serializers"><a class="toclink" href="#serializers">Serializers</a></h2>
<p>First up we're going to define some serializers. Let's create a new module named <code>tutorial/quickstart/serializers.py</code> that we'll use for our data representations.</p>
<pre><code>from django.contrib.auth.models import User, Group
<pre><code>from django.contrib.auth.models import Group, User
from rest_framework import serializers
@ -532,10 +530,10 @@ class GroupSerializer(serializers.HyperlinkedModelSerializer):
<p>Notice that we're using hyperlinked relations in this case with <code>HyperlinkedModelSerializer</code>. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.</p>
<h2 id="views"><a class="toclink" href="#views">Views</a></h2>
<p>Right, we'd better write some views then. Open <code>tutorial/quickstart/views.py</code> and get typing.</p>
<pre><code>from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
<pre><code>from django.contrib.auth.models import Group, User
from rest_framework import permissions, viewsets
from tutorial.quickstart.serializers import GroupSerializer, UserSerializer
class UserViewSet(viewsets.ModelViewSet):
@ -561,6 +559,7 @@ class GroupViewSet(viewsets.ModelViewSet):
<p>Okay, now let's wire up the API URLs. On to <code>tutorial/urls.py</code>...</p>
<pre><code>from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views
router = routers.DefaultRouter()
@ -573,6 +572,8 @@ urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
urlpatterns += router.urls
</code></pre>
<p>Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.</p>
<p>Again, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.</p>
@ -598,9 +599,29 @@ urlpatterns = [
<pre><code>python manage.py runserver
</code></pre>
<p>We can now access our API, both from the command-line, using tools like <code>curl</code>...</p>
<pre><code>bash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
<pre><code>bash: curl -u admin -H 'Accept: application/json; indent=4' http://127.0.0.1:8000/users/
Enter host password for user 'admin':
{
"count": 2,
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin",
"email": "admin@example.com",
"groups": []
}
]
}
</code></pre>
<p>Or using the <a href="https://httpie.io/docs#installation">httpie</a>, command line tool...</p>
<pre><code>bash: http -a admin http://127.0.0.1:8000/users/
http: password for admin@127.0.0.1:8000::
$HTTP/1.1 200 OK
...
{
"count": 1,
"next": null,
"previous": null,
"results": [
@ -609,26 +630,7 @@ urlpatterns = [
"groups": [],
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin"
},
]
}
</code></pre>
<p>Or using the <a href="https://httpie.io/docs#installation">httpie</a>, command line tool...</p>
<pre><code>bash: http -a admin:password123 http://127.0.0.1:8000/users/
HTTP/1.1 200 OK
...
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"email": "admin@example.com",
"groups": [],
"url": "http://localhost:8000/users/1/",
"username": "paul"
},
}
]
}
</code></pre>