mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-27 17:54:08 +03:00
Deployed a83997e
with MkDocs version: 0.15.3
This commit is contained in:
parent
21d73ebf37
commit
76288687db
|
@ -520,52 +520,80 @@ 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> and <code>.default_detail</code> properties 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
|
||||
|
||||
class ServiceUnavailable(APIException):
|
||||
status_code = 503
|
||||
default_detail = 'Service temporarily unavailable, try again later.'
|
||||
default_code = 'service_unavailable'
|
||||
</code></pre>
|
||||
<h4 id="inspecting-api-exceptions"><a class="toclink" href="#inspecting-api-exceptions">Inspecting API exceptions</a></h4>
|
||||
<p>There are a number of different properties available for inspecting the status
|
||||
of an API exception. You can use these to build custom exception handling
|
||||
for your project.</p>
|
||||
<p>The available attributes and methods are:</p>
|
||||
<ul>
|
||||
<li><code>.detail</code> - Return the textual description of the error.</li>
|
||||
<li><code>.get_codes()</code> - Return the code identifier of the error.</li>
|
||||
<li><code>.full_details()</code> - Return both the textual description and the code identifier.</li>
|
||||
</ul>
|
||||
<p>In most cases the error detail will be a simple item:</p>
|
||||
<pre><code>>>> print(exc.detail)
|
||||
You do not have permission to perform this action.
|
||||
>>> print(exc.get_codes())
|
||||
permission_denied
|
||||
>>> print(exc.full_details())
|
||||
{'message':'You do not have permission to perform this action.','code':'permission_denied'}
|
||||
</code></pre>
|
||||
<p>In the case of validation errors the error detail will be either a list or
|
||||
dictionary of items:</p>
|
||||
<pre><code>>>> print(exc.detail)
|
||||
{"name":"This field is required.","age":"A valid integer is required."}
|
||||
>>> print(exc.get_codes())
|
||||
{"name":"required","age":"invalid"}
|
||||
>>> print(exc.get_full_details())
|
||||
{"name":{"message":"This field is required.","code":"required"},"age":{"message":"A valid integer is required.","code":"invalid"}}
|
||||
</code></pre>
|
||||
<h2 id="parseerror"><a class="toclink" href="#parseerror">ParseError</a></h2>
|
||||
<p><strong>Signature:</strong> <code>ParseError(detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>ParseError(detail=None, code=None)</code></p>
|
||||
<p>Raised if the request contains malformed data when accessing <code>request.data</code>.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
|
||||
<h2 id="authenticationfailed"><a class="toclink" href="#authenticationfailed">AuthenticationFailed</a></h2>
|
||||
<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None, code=None)</code></p>
|
||||
<p>Raised when an incoming request includes incorrect authentication.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="../authentication/">authentication documentation</a> for more details.</p>
|
||||
<h2 id="notauthenticated"><a class="toclink" href="#notauthenticated">NotAuthenticated</a></h2>
|
||||
<p><strong>Signature:</strong> <code>NotAuthenticated(detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>NotAuthenticated(detail=None, code=None)</code></p>
|
||||
<p>Raised when an unauthenticated request fails the permission checks.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="../authentication/">authentication documentation</a> for more details.</p>
|
||||
<h2 id="permissiondenied"><a class="toclink" href="#permissiondenied">PermissionDenied</a></h2>
|
||||
<p><strong>Signature:</strong> <code>PermissionDenied(detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>PermissionDenied(detail=None, code=None)</code></p>
|
||||
<p>Raised when an authenticated request fails the permission checks.</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></p>
|
||||
<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>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></p>
|
||||
<p><strong>Signature:</strong> <code>MethodNotAllowed(method, detail=None, code=None)</code></p>
|
||||
<p>Raised when an incoming request occurs that does not map to a handler method on the view.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "405 Method Not Allowed".</p>
|
||||
<h2 id="notacceptable"><a class="toclink" href="#notacceptable">NotAcceptable</a></h2>
|
||||
<p><strong>Signature:</strong> <code>NotAcceptable(detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>NotAcceptable(detail=None, code=None)</code></p>
|
||||
<p>Raised when an incoming request occurs with an <code>Accept</code> header that cannot be satisfied by any of the available renderers.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "406 Not Acceptable".</p>
|
||||
<h2 id="unsupportedmediatype"><a class="toclink" href="#unsupportedmediatype">UnsupportedMediaType</a></h2>
|
||||
<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None, code=None)</code></p>
|
||||
<p>Raised if there are no parsers that can handle the content type of the request data when accessing <code>request.data</code>.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p>
|
||||
<h2 id="throttled"><a class="toclink" href="#throttled">Throttled</a></h2>
|
||||
<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None)</code></p>
|
||||
<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None, code=None)</code></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></p>
|
||||
<p><strong>Signature:</strong> <code>ValidationError(detail, 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>
|
||||
|
|
|
@ -786,7 +786,7 @@ color_channel = serializers.ChoiceField(
|
|||
<p>Format strings may either be <a href="http://docs.python.org/2/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="http://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>In the case of JSON this means the default datetime representation uses the <a href="http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15">ECMA 262 date time string specification</a>. This is a subset of ISO 8601 which uses millisecond precision, and includes the 'Z' suffix for the UTC timezone, for example: <code>2013-01-29T12:34:56.123Z</code>.</p>
|
||||
<h4 id="auto_now-and-auto_now_add-model-fields"><code>auto_now_add</code> model fields.<a class="toclink" href="#auto_now-and-auto_now_add-model-fields"><code>auto_now</code> and </a></h4>
|
||||
<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>
|
||||
<pre><code>class CommentSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -432,6 +432,10 @@
|
|||
<a href="#customizing-the-interface">Customizing the interface</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#pagination-schemas">Pagination & schemas</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#third-party-packages">Third party packages</a>
|
||||
|
@ -450,6 +454,10 @@
|
|||
<a href="#django-url-filter">Django URL Filter</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#drf-url-filters">drf-url-filters</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
|
@ -788,6 +796,10 @@ class ProductFilter(filters.FilterSet):
|
|||
<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="pagination-schemas"><a class="toclink" href="#pagination-schemas">Pagination & 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,
|
||||
which 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>
|
||||
|
@ -796,6 +808,8 @@ class ProductFilter(filters.FilterSet):
|
|||
<p>The <a href="https://github.com/trollknurr/django-rest-framework-word-search-filter">djangorestframework-word-filter</a> developed as alternative to <code>filters.SearchFilter</code> which will search full word in text, or exact match.</p>
|
||||
<h2 id="django-url-filter"><a class="toclink" href="#django-url-filter">Django URL Filter</a></h2>
|
||||
<p><a href="https://github.com/miki725/django-url-filter">django-url-filter</a> provides a safe way to filter data via human-friendly URLs. It works very similar to DRF serializers and fields in a sense that they can be nested except they are called filtersets and filters. That provides easy way to filter related data. Also this library is generic-purpose so it can be used to filter other sources of data and not only Django <code>QuerySet</code>s.</p>
|
||||
<h2 id="drf-url-filters"><a class="toclink" href="#drf-url-filters">drf-url-filters</a></h2>
|
||||
<p><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. A beautiful python package <code>Voluptuous</code> is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
|
|
|
@ -667,7 +667,6 @@ class UserList(generics.ListCreateAPIView):
|
|||
<p>Provides a <code>.update(request, *args, **kwargs)</code> method, that implements updating and saving an existing model instance.</p>
|
||||
<p>Also provides a <code>.partial_update(request, *args, **kwargs)</code> method, which is similar to the <code>update</code> method, except that all fields for the update will be optional. This allows support for HTTP <code>PATCH</code> requests.</p>
|
||||
<p>If an object is updated this returns a <code>200 OK</code> response, with a serialized representation of the object as the body of the response.</p>
|
||||
<p>If an object is created, for example when making a <code>DELETE</code> request followed by a <code>PUT</code> request to the same URL, this returns a <code>201 Created</code> response, with a serialized representation of the object as the body of the response.</p>
|
||||
<p>If the request data provided for updating the object was invalid, a <code>400 Bad Request</code> response will be returned, with the error details as the body of the response.</p>
|
||||
<h2 id="destroymodelmixin"><a class="toclink" href="#destroymodelmixin">DestroyModelMixin</a></h2>
|
||||
<p>Provides a <code>.destroy(request, *args, **kwargs)</code> method, that implements deletion of an existing model instance.</p>
|
||||
|
|
|
@ -410,6 +410,10 @@
|
|||
<a href="#using-your-custom-pagination-class">Using your custom pagination class</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#pagination-schemas">Pagination & schemas</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#html-pagination-controls">HTML pagination controls</a>
|
||||
|
@ -666,6 +670,10 @@ 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>
|
||||
<h2 id="pagination-schemas"><a class="toclink" href="#pagination-schemas">Pagination & 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,
|
||||
which should return a list of <code>coreapi.Field</code> instances.</p>
|
||||
<hr />
|
||||
<p><img alt="Link Header" src="../../img/link-header-pagination.png" /></p>
|
||||
<p><em>A custom pagination style, using the 'Link' header'</em></p>
|
||||
|
|
|
@ -574,8 +574,8 @@ class Track(models.Model):
|
|||
</code></pre>
|
||||
<p>Would serialize to a representation like this:</p>
|
||||
<pre><code>{
|
||||
'album_name': 'The Roots',
|
||||
'artist': 'Undun',
|
||||
'album_name': 'Undun',
|
||||
'artist': 'The Roots',
|
||||
'tracks': [
|
||||
89,
|
||||
90,
|
||||
|
@ -868,6 +868,7 @@ class CustomerHyperlink(serializers.HyperlinkedRelatedField):
|
|||
<li><code>html_cutoff</code> - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Set to <code>None</code> to disable any limiting. Defaults to <code>1000</code>.</li>
|
||||
<li><code>html_cutoff_text</code> - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to <code>"More than {count} items…"</code></li>
|
||||
</ul>
|
||||
<p>You can also control these globally using the settings <code>HTML_SELECT_CUTOFF</code> and <code>HTML_SELECT_CUTOFF_TEXT</code>.</p>
|
||||
<p>In cases where the cutoff is being enforced you may want to instead use a plain input field in the HTML form. You can do so using the <code>style</code> keyword argument. For example:</p>
|
||||
<pre><code>assigned_to = serializers.SlugRelatedField(
|
||||
queryset=User.objects.all(),
|
||||
|
|
|
@ -412,7 +412,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/dev/topics/http/urls/#reverse"><code>django.core.urlresolvers.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/dev/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>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
|
||||
|
@ -429,7 +429,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/dev/topics/http/urls/#reverse-lazy"><code>django.core.urlresolvers.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/dev/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>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>
|
||||
|
|
|
@ -385,11 +385,11 @@
|
|||
|
||||
|
||||
<li>
|
||||
<a href="#using-defaultrouter">Using DefaultRouter</a>
|
||||
<a href="#the-get_schema_view-shortcut">The get_schema_view shortcut</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#using-schemagenerator">Using SchemaGenerator</a>
|
||||
<a href="#using-an-explicit-schema-view">Using an explicit schema view</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
@ -401,6 +401,16 @@
|
|||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#schemas-as-documentation">Schemas as documentation</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#examples">Examples</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#alternate-schema-formats">Alternate schema formats</a>
|
||||
</li>
|
||||
|
@ -528,13 +538,18 @@ for REST framework.</p>
|
|||
<p>REST framework includes functionality for auto-generating a schema,
|
||||
or allows you to specify one explicitly. There are a few different ways to
|
||||
add a schema to your API, depending on exactly what you need.</p>
|
||||
<h2 id="using-defaultrouter"><a class="toclink" href="#using-defaultrouter">Using DefaultRouter</a></h2>
|
||||
<p>If you're using <code>DefaultRouter</code> then you can include an auto-generated schema,
|
||||
simply by adding a <code>schema_title</code> argument to the router.</p>
|
||||
<pre><code>router = DefaultRouter(schema_title='Server Monitoring API')
|
||||
<h2 id="the-get_schema_view-shortcut"><a class="toclink" href="#the-get_schema_view-shortcut">The get_schema_view shortcut</a></h2>
|
||||
<p>The simplest way to include a schema in your project is to use the
|
||||
<code>get_schema_view()</code> function.</p>
|
||||
<pre><code>schema_view = get_schema_view(title="Server Monitoring API")
|
||||
|
||||
urlpatterns = [
|
||||
url('^$', schema_view),
|
||||
...
|
||||
]
|
||||
</code></pre>
|
||||
<p>The schema will be included at the root URL, <code>/</code>, and presented to clients
|
||||
that include the Core JSON media type in their <code>Accept</code> header.</p>
|
||||
<p>Once the view has been added, you'll be able to make API requests to retrieve
|
||||
the auto-generated schema definition.</p>
|
||||
<pre><code>$ http http://127.0.0.1:8000/ Accept:application/vnd.coreapi+json
|
||||
HTTP/1.0 200 OK
|
||||
Allow: GET, HEAD, OPTIONS
|
||||
|
@ -548,49 +563,47 @@ Content-Type: application/vnd.coreapi+json
|
|||
...
|
||||
}
|
||||
</code></pre>
|
||||
<p>This is a great zero-configuration option for when you want to get up and
|
||||
running really quickly.</p>
|
||||
<p>The other available options to <code>DefaultRouter</code> are:</p>
|
||||
<h4 id="schema_renderers"><a class="toclink" href="#schema_renderers">schema_renderers</a></h4>
|
||||
<p>May be used to pass the set of renderer classes that can be used to render schema output.</p>
|
||||
<p>The arguments to <code>get_schema_view()</code> are:</p>
|
||||
<h4 id="title"><a class="toclink" href="#title"><code>title</code></a></h4>
|
||||
<p>May be used to provide a descriptive title for the schema definition.</p>
|
||||
<h4 id="url"><a class="toclink" href="#url"><code>url</code></a></h4>
|
||||
<p>May be used to pass a canonical URL for the schema.</p>
|
||||
<pre><code>schema_view = get_schema_view(
|
||||
title='Server Monitoring API',
|
||||
url='https://www.example.org/api/'
|
||||
)
|
||||
</code></pre>
|
||||
<h4 id="renderer_classes"><a class="toclink" href="#renderer_classes"><code>renderer_classes</code></a></h4>
|
||||
<p>May be used to pass the set of renderer classes that can be used to render the API root endpoint.</p>
|
||||
<pre><code>from rest_framework.renderers import CoreJSONRenderer
|
||||
from my_custom_package import APIBlueprintRenderer
|
||||
|
||||
router = DefaultRouter(schema_title='Server Monitoring API', schema_renderers=[
|
||||
CoreJSONRenderer, APIBlueprintRenderer
|
||||
])
|
||||
</code></pre>
|
||||
<h4 id="schema_url"><a class="toclink" href="#schema_url">schema_url</a></h4>
|
||||
<p>May be used to pass the root URL for the schema. This can either be used to ensure that
|
||||
the schema URLs include a canonical hostname and schema, or to ensure that all the
|
||||
schema URLs include a path prefix.</p>
|
||||
<pre><code>router = DefaultRouter(
|
||||
schema_title='Server Monitoring API',
|
||||
schema_url='https://www.example.org/api/'
|
||||
schema_view = get_schema_view(
|
||||
title='Server Monitoring API',
|
||||
url='https://www.example.org/api/',
|
||||
renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]
|
||||
)
|
||||
</code></pre>
|
||||
<p>If you want more flexibility over the schema output then you'll need to consider
|
||||
using <code>SchemaGenerator</code> instead.</p>
|
||||
<h4 id="root_renderers"><a class="toclink" href="#root_renderers">root_renderers</a></h4>
|
||||
<p>May be used to pass the set of renderer classes that can be used to render the API root endpoint.</p>
|
||||
<h2 id="using-schemagenerator"><a class="toclink" href="#using-schemagenerator">Using SchemaGenerator</a></h2>
|
||||
<p>The most common way to add a schema to your API is to use the <code>SchemaGenerator</code>
|
||||
class to auto-generate the <code>Document</code> instance, and to return that from a view.</p>
|
||||
<h2 id="using-an-explicit-schema-view"><a class="toclink" href="#using-an-explicit-schema-view">Using an explicit schema view</a></h2>
|
||||
<p>If you need a little more control than the <code>get_schema_view()</code> shortcut gives you,
|
||||
then you can use the <code>SchemaGenerator</code> class directly to auto-generate the
|
||||
<code>Document</code> instance, and to return that from a view.</p>
|
||||
<p>This option gives you the flexibility of setting up the schema endpoint
|
||||
with whatever behavior you want. For example, you can apply different
|
||||
permission, throttling or authentication policies to the schema endpoint.</p>
|
||||
with whatever behaviour you want. For example, you can apply different
|
||||
permission, throttling, or authentication policies to the schema endpoint.</p>
|
||||
<p>Here's an example of using <code>SchemaGenerator</code> together with a view to
|
||||
return the schema.</p>
|
||||
<p><strong>views.py:</strong></p>
|
||||
<pre><code>from rest_framework.decorators import api_view, renderer_classes
|
||||
from rest_framework import renderers, response, schemas
|
||||
|
||||
generator = schemas.SchemaGenerator(title='Bookings API')
|
||||
|
||||
@api_view()
|
||||
@renderer_classes([renderers.CoreJSONRenderer])
|
||||
def schema_view(request):
|
||||
generator = schemas.SchemaGenerator(title='Bookings API')
|
||||
return response.Response(generator.get_schema())
|
||||
schema = generator.get_schema(request)
|
||||
return response.Response(schema)
|
||||
</code></pre>
|
||||
<p><strong>urls.py:</strong></p>
|
||||
<pre><code>urlpatterns = [
|
||||
|
@ -642,6 +655,60 @@ of the available formats, such as Core JSON or Open API.</p>
|
|||
rendered to one of many available formats, depending on the client request.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h1 id="schemas-as-documentation"><a class="toclink" href="#schemas-as-documentation">Schemas as documentation</a></h1>
|
||||
<p>One common usage of API schemas is to use them to build documentation pages.</p>
|
||||
<p>The schema generation in REST framework uses docstrings to automatically
|
||||
populate descriptions in the schema document.</p>
|
||||
<p>These descriptions will be based on:</p>
|
||||
<ul>
|
||||
<li>The corresponding method docstring if one exists.</li>
|
||||
<li>A named section within the class docstring, which can be either single line or multi-line.</li>
|
||||
<li>The class docstring.</li>
|
||||
</ul>
|
||||
<h2 id="examples"><a class="toclink" href="#examples">Examples</a></h2>
|
||||
<p>An <code>APIView</code>, with an explicit method docstring.</p>
|
||||
<pre><code>class ListUsernames(APIView):
|
||||
def get(self, request):
|
||||
"""
|
||||
Return a list of all user names in the system.
|
||||
"""
|
||||
usernames = [user.username for user in User.objects.all()]
|
||||
return Response(usernames)
|
||||
</code></pre>
|
||||
<p>A <code>ViewSet</code>, with an explict action docstring.</p>
|
||||
<pre><code>class ListUsernames(ViewSet):
|
||||
def list(self, request):
|
||||
"""
|
||||
Return a list of all user names in the system.
|
||||
"""
|
||||
usernames = [user.username for user in User.objects.all()]
|
||||
return Response(usernames)
|
||||
</code></pre>
|
||||
<p>A generic view with sections in the class docstring, using single-line style.</p>
|
||||
<pre><code>class UserList(generics.ListCreateAPIView):
|
||||
"""
|
||||
get: Create a new user.
|
||||
post: List all the users.
|
||||
"""
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = (IsAdminUser,)
|
||||
</code></pre>
|
||||
<p>A generic viewset with sections in the class docstring, using multi-line style.</p>
|
||||
<pre><code>class UserViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows users to be viewed or edited.
|
||||
|
||||
retrieve:
|
||||
Return a user instance.
|
||||
|
||||
list:
|
||||
Return all users, ordered by most recently joined.
|
||||
"""
|
||||
queryset = User.objects.all().order_by('-date_joined')
|
||||
serializer_class = UserSerializer
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="alternate-schema-formats"><a class="toclink" href="#alternate-schema-formats">Alternate schema formats</a></h1>
|
||||
<p>In order to support an alternate schema format, you need to implement a custom renderer
|
||||
class that handles converting a <code>Document</code> instance into a bytestring representation.</p>
|
||||
|
@ -696,9 +763,9 @@ package that are used to represent an API schema.</p>
|
|||
from the <code>rest_framework</code> package.</p>
|
||||
<h3 id="document"><a class="toclink" href="#document">Document</a></h3>
|
||||
<p>Represents a container for the API schema.</p>
|
||||
<h4 id="title"><a class="toclink" href="#title"><code>title</code></a></h4>
|
||||
<h4 id="title_1"><a class="toclink" href="#title_1"><code>title</code></a></h4>
|
||||
<p>A name for the API.</p>
|
||||
<h4 id="url"><a class="toclink" href="#url"><code>url</code></a></h4>
|
||||
<h4 id="url_1"><a class="toclink" href="#url_1"><code>url</code></a></h4>
|
||||
<p>A canonical URL for the API.</p>
|
||||
<h4 id="content"><a class="toclink" href="#content"><code>content</code></a></h4>
|
||||
<p>A dictionary, containing the <code>Link</code> objects that the schema contains.</p>
|
||||
|
@ -719,7 +786,7 @@ may be nested, typically to a second level. For example:</p>
|
|||
</code></pre>
|
||||
<h3 id="link"><a class="toclink" href="#link">Link</a></h3>
|
||||
<p>Represents an individual API endpoint.</p>
|
||||
<h4 id="url_1"><a class="toclink" href="#url_1"><code>url</code></a></h4>
|
||||
<h4 id="url_2"><a class="toclink" href="#url_2"><code>url</code></a></h4>
|
||||
<p>The URL of the endpoint. May be a URI template, such as <code>/users/{username}/</code>.</p>
|
||||
<h4 id="action"><a class="toclink" href="#action"><code>action</code></a></h4>
|
||||
<p>The HTTP method associated with the endpoint. Note that URLs that support
|
||||
|
|
|
@ -550,6 +550,10 @@
|
|||
<a href="#dynamic-rest">Dynamic REST</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#dynamic-fields-mixin">Dynamic Fields Mixin</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#html-json-forms">HTML JSON Forms</a>
|
||||
</li>
|
||||
|
@ -1418,6 +1422,8 @@ def all_high_scores(request):
|
|||
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreSerializer</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field and its <code>schema-mode</code> feature.</p>
|
||||
<h2 id="dynamic-rest"><a class="toclink" href="#dynamic-rest">Dynamic REST</a></h2>
|
||||
<p>The <a href="https://github.com/AltSchool/dynamic-rest">dynamic-rest</a> package extends the ModelSerializer and ModelViewSet interfaces, adding API query parameters for filtering, sorting, and including / excluding all fields and relationships defined by your serializers.</p>
|
||||
<h2 id="dynamic-fields-mixin"><a class="toclink" href="#dynamic-fields-mixin">Dynamic Fields Mixin</a></h2>
|
||||
<p>The <a href="https://github.com/dbrgn/drf-dynamic-fields">drf-dynamic-fields</a> package provides a mixin to dynamically limit the fields per serializer to a subset specified by an URL parameter.</p>
|
||||
<h2 id="html-json-forms"><a class="toclink" href="#html-json-forms">HTML JSON Forms</a></h2>
|
||||
<p>The <a href="https://github.com/wq/html-json-forms">html-json-forms</a> package provides an algorithm and serializer for processing <code><form></code> submissions per the (inactive) <a href="https://www.w3.org/TR/html-json-forms/">HTML JSON Form specification</a>. The serializer facilitates processing of arbitrarily nested JSON structures within HTML. For example, <code><input name="items[0][id]" value="5"></code> will be interpreted as <code>{"items": [{"id": "5"}]}</code>.</p>
|
||||
|
||||
|
|
|
@ -396,6 +396,10 @@
|
|||
<a href="#test-settings">Test settings</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#schema-generation-controls">Schema generation controls</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#content-type-controls">Content type controls</a>
|
||||
</li>
|
||||
|
@ -412,6 +416,10 @@
|
|||
<a href="#view-names-and-descriptions">View names and descriptions</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#html-select-field-cutoffs">HTML Select Field cutoffs</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#miscellaneous-settings">Miscellaneous settings</a>
|
||||
</li>
|
||||
|
@ -577,6 +585,20 @@ If set to <code>None</code> then generic filtering is disabled.</p>
|
|||
)
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="schema-generation-controls"><a class="toclink" href="#schema-generation-controls">Schema generation controls</a></h2>
|
||||
<h4 id="schema_coerce_path_pk"><a class="toclink" href="#schema_coerce_path_pk">SCHEMA_COERCE_PATH_PK</a></h4>
|
||||
<p>If set, this maps the <code>'pk'</code> identifier in the URL conf onto the actual field
|
||||
name when generating a schema path parameter. Typically this will be <code>'id'</code>.
|
||||
This gives a more suitable representation as "primary key" is an implementation
|
||||
detail, wheras "identifier" is a more general concept.</p>
|
||||
<p>Default: <code>True</code></p>
|
||||
<h4 id="schema_coerce_method_names"><a class="toclink" href="#schema_coerce_method_names">SCHEMA_COERCE_METHOD_NAMES</a></h4>
|
||||
<p>If set, this is used to map internal viewset method names onto external action
|
||||
names used in the schema generation. This allows us to generate names that
|
||||
are more suitable for an external representation than those that are used
|
||||
internally in the codebase.</p>
|
||||
<p>Default: <code>{'retrieve': 'read', 'destroy': 'delete'}</code></p>
|
||||
<hr />
|
||||
<h2 id="content-type-controls"><a class="toclink" href="#content-type-controls">Content type controls</a></h2>
|
||||
<h4 id="url_format_override"><a class="toclink" href="#url_format_override">URL_FORMAT_OVERRIDE</a></h4>
|
||||
<p>The name of a URL parameter that may be used to override the default content negotiation <code>Accept</code> header behavior, by using a <code>format=…</code> query parameter in the request URL.</p>
|
||||
|
@ -662,6 +684,14 @@ If set to <code>None</code> then generic filtering is disabled.</p>
|
|||
<li><code>html</code>: A boolean indicating if HTML output is required. <code>True</code> when used in the browsable API, and <code>False</code> when used in generating <code>OPTIONS</code> responses.</li>
|
||||
</ul>
|
||||
<p>Default: <code>'rest_framework.views.get_view_description'</code></p>
|
||||
<h2 id="html-select-field-cutoffs"><a class="toclink" href="#html-select-field-cutoffs">HTML Select Field cutoffs</a></h2>
|
||||
<p>Global settings for <a href="../relations/#select-field-cutoffs">select field cutoffs for rendering relational fields</a> in the browsable API.</p>
|
||||
<h4 id="html_select_cutoff"><a class="toclink" href="#html_select_cutoff">HTML_SELECT_CUTOFF</a></h4>
|
||||
<p>Global setting for the <code>html_cutoff</code> value. Must be an integer.</p>
|
||||
<p>Default: 1000</p>
|
||||
<h4 id="html_select_cutoff_text"><a class="toclink" href="#html_select_cutoff_text">HTML_SELECT_CUTOFF_TEXT</a></h4>
|
||||
<p>A string representing a global setting for <code>html_cutoff_text</code>.</p>
|
||||
<p>Default: <code>"More than {count} items..."</code></p>
|
||||
<hr />
|
||||
<h2 id="miscellaneous-settings"><a class="toclink" href="#miscellaneous-settings">Miscellaneous settings</a></h2>
|
||||
<h4 id="exception_handler"><a class="toclink" href="#exception_handler">EXCEPTION_HANDLER</a></h4>
|
||||
|
|
|
@ -403,6 +403,34 @@
|
|||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#requestsclient">RequestsClient</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#headers-authentication">Headers & Authentication</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#csrf">CSRF</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#live-tests">Live tests</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#coreapiclient">CoreAPIClient</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#headers-authentication_1">Headers & Authentication</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#test-cases">Test cases</a>
|
||||
</li>
|
||||
|
@ -593,6 +621,80 @@ client.force_authenticate(user=user)
|
|||
</code></pre>
|
||||
<p>As usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling <code>login()</code>.</p>
|
||||
<hr />
|
||||
<h1 id="requestsclient"><a class="toclink" href="#requestsclient">RequestsClient</a></h1>
|
||||
<p>REST framework also includes a client for interacting with your application
|
||||
using the popular Python library, <code>requests</code>.</p>
|
||||
<p>This exposes exactly the same interface as if you were using a requests session
|
||||
directly.</p>
|
||||
<pre><code>client = RequestsClient()
|
||||
response = client.get('http://testserver/users/')
|
||||
</code></pre>
|
||||
<p>Note that the requests client requires you to pass fully qualified URLs.</p>
|
||||
<h2 id="headers-authentication"><a class="toclink" href="#headers-authentication">Headers & Authentication</a></h2>
|
||||
<p>Custom headers and authentication credentials can be provided in the same way
|
||||
as <a href="http://docs.python-requests.org/en/master/user/advanced/#session-objects">when using a standard <code>requests.Session</code> instance</a>.</p>
|
||||
<pre><code>from requests.auth import HTTPBasicAuth
|
||||
|
||||
client.auth = HTTPBasicAuth('user', 'pass')
|
||||
client.headers.update({'x-test': 'true'})
|
||||
</code></pre>
|
||||
<h2 id="csrf"><a class="toclink" href="#csrf">CSRF</a></h2>
|
||||
<p>If you're using <code>SessionAuthentication</code> then you'll need to include a CSRF token
|
||||
for any <code>POST</code>, <code>PUT</code>, <code>PATCH</code> or <code>DELETE</code> requests.</p>
|
||||
<p>You can do so by following the same flow that a JavaScript based client would use.
|
||||
First make a <code>GET</code> request in order to obtain a CRSF token, then present that
|
||||
token in the following request.</p>
|
||||
<p>For example...</p>
|
||||
<pre><code>client = RequestsClient()
|
||||
|
||||
# Obtain a CSRF token.
|
||||
response = client.get('/homepage/')
|
||||
assert response.status_code == 200
|
||||
csrftoken = response.cookies['csrftoken']
|
||||
|
||||
# Interact with the API.
|
||||
response = client.post('/organisations/', json={
|
||||
'name': 'MegaCorp',
|
||||
'status': 'active'
|
||||
}, headers={'X-CSRFToken': csrftoken})
|
||||
assert response.status_code == 200
|
||||
</code></pre>
|
||||
<h2 id="live-tests"><a class="toclink" href="#live-tests">Live tests</a></h2>
|
||||
<p>With careful usage both the <code>RequestsClient</code> and the <code>CoreAPIClient</code> provide
|
||||
the ability to write test cases that can run either in development, or be run
|
||||
directly against your staging server or production environment.</p>
|
||||
<p>Using this style to create basic tests of a few core piece of functionality is
|
||||
a powerful way to validate your live service. Doing so may require some careful
|
||||
attention to setup and teardown to ensure that the tests run in a way that they
|
||||
do not directly affect customer data.</p>
|
||||
<hr />
|
||||
<h1 id="coreapiclient"><a class="toclink" href="#coreapiclient">CoreAPIClient</a></h1>
|
||||
<p>The CoreAPIClient allows you to interact with your API using the Python
|
||||
<code>coreapi</code> client library.</p>
|
||||
<pre><code># Fetch the API schema
|
||||
url = reverse('schema')
|
||||
client = CoreAPIClient()
|
||||
schema = client.get(url)
|
||||
|
||||
# Create a new organisation
|
||||
params = {'name': 'MegaCorp', 'status': 'active'}
|
||||
client.action(schema, ['organisations', 'create'], params)
|
||||
|
||||
# Ensure that the organisation exists in the listing
|
||||
data = client.action(schema, ['organisations', 'list'])
|
||||
assert(len(data) == 1)
|
||||
assert(data == [{'name': 'MegaCorp', 'status': 'active'}])
|
||||
</code></pre>
|
||||
<h2 id="headers-authentication_1"><a class="toclink" href="#headers-authentication_1">Headers & Authentication</a></h2>
|
||||
<p>Custom headers and authentication may be used with <code>CoreAPIClient</code> in a
|
||||
similar way as with <code>RequestsClient</code>.</p>
|
||||
<pre><code>from requests.auth import HTTPBasicAuth
|
||||
|
||||
client = CoreAPIClient()
|
||||
client.session.auth = HTTPBasicAuth('user', 'pass')
|
||||
client.session.headers.update({'x-test': 'true'})
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="test-cases"><a class="toclink" href="#test-cases">Test cases</a></h1>
|
||||
<p>REST framework includes the following test case classes, that mirror the existing Django test case classes, but use <code>APIClient</code> instead of Django's default <code>Client</code>.</p>
|
||||
<ul>
|
||||
|
@ -603,7 +705,7 @@ client.force_authenticate(user=user)
|
|||
</ul>
|
||||
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
|
||||
<p>You can use any of REST framework's test case classes as you would for the regular Django test case classes. The <code>self.client</code> attribute will be an <code>APIClient</code> instance.</p>
|
||||
<pre><code>from django.core.urlresolvers import reverse
|
||||
<pre><code>from django.urls import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from myproject.apps.core.models import Account
|
||||
|
|
|
@ -504,6 +504,7 @@ It takes a single required argument, and an optional <code>messages</code> argum
|
|||
<ul>
|
||||
<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
|
||||
<li><code>message</code> - The error message that should be used when validation fails.</li>
|
||||
<li><code>lookup</code> - The lookup used to find an existing instance with the value being validated. Defaults to <code>'exact'</code>.</li>
|
||||
</ul>
|
||||
<p>This validator should be applied to <em>serializer fields</em>, like so:</p>
|
||||
<pre><code>from rest_framework.validators import UniqueValidator
|
||||
|
|
|
@ -503,7 +503,7 @@ This method is used to enforce permissions and throttling, and perform content n
|
|||
</blockquote>
|
||||
<p>REST framework also allows you to work with regular function based views. It provides a set of simple decorators that wrap your function based views to ensure they receive an instance of <code>Request</code> (rather than the usual Django <code>HttpRequest</code>) and allows them to return a <code>Response</code> (instead of a Django <code>HttpResponse</code>), and allow you to configure how the request is processed.</p>
|
||||
<h2 id="api_view"><a class="toclink" href="#api_view">@api_view()</a></h2>
|
||||
<p><strong>Signature:</strong> <code>@api_view(http_method_names=['GET'])</code></p>
|
||||
<p><strong>Signature:</strong> <code>@api_view(http_method_names=['GET'], exclude_from_schema=False)</code></p>
|
||||
<p>The core of this functionality is the <code>api_view</code> decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:</p>
|
||||
<pre><code>from rest_framework.decorators import api_view
|
||||
|
||||
|
@ -512,13 +512,19 @@ 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 behavior, 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 behaviour, specify which methods the view allows, like so:</p>
|
||||
<pre><code>@api_view(['GET', 'POST'])
|
||||
def hello_world(request):
|
||||
if request.method == 'POST':
|
||||
return Response({"message": "Got some data!", "data": request.data})
|
||||
return Response({"message": "Hello, world!"})
|
||||
</code></pre>
|
||||
<p>You can also mark an API view as being omitted from any <a href="../schemas/">auto-generated schema</a>,
|
||||
using the <code>exclude_from_schema</code> argument.:</p>
|
||||
<pre><code>@api_view(['GET'], exclude_from_schema=True)
|
||||
def api_docs(request):
|
||||
...
|
||||
</code></pre>
|
||||
<h2 id="api-policy-decorators"><a class="toclink" href="#api-policy-decorators">API policy decorators</a></h2>
|
||||
<p>To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come <em>after</em> (below) the <code>@api_view</code> decorator. For example, to create a view that uses a <a href="../throttling/">throttle</a> to ensure it can only be called once per day by a particular user, use the <code>@throttle_classes</code> decorator, passing a list of throttle classes:</p>
|
||||
<pre><code>from rest_framework.decorators import api_view, throttle_classes
|
||||
|
|
File diff suppressed because one or more lines are too long
112
sitemap.xml
112
sitemap.xml
|
@ -4,7 +4,7 @@
|
|||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
|
@ -13,49 +13,49 @@
|
|||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/quickstart/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/1-serialization/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/2-requests-and-responses/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/3-class-based-views/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/4-authentication-and-permissions/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/5-relationships-and-hyperlinked-apis/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/6-viewsets-and-routers/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//tutorial/7-schemas-and-client-libraries/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
|
@ -65,163 +65,163 @@
|
|||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/requests/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/responses/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/views/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/generic-views/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/viewsets/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/routers/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/parsers/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/renderers/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/serializers/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/fields/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/relations/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/validators/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/authentication/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/permissions/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/throttling/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/filtering/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/pagination/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/versioning/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/content-negotiation/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/metadata/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/schemas/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/format-suffixes/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/reverse/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/exceptions/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/status-codes/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/testing/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//api-guide/settings/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
|
@ -231,121 +231,121 @@
|
|||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/documenting-your-api/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/api-clients/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/internationalization/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/ajax-csrf-cors/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/html-and-forms/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/browser-enhancements/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/browsable-api/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/rest-hypermedia-hateoas/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/third-party-resources/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/contributing/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/project-management/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/3.0-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/3.1-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/3.2-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/3.3-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/3.4-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/kickstarter-announcement/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/mozilla-grant/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/funding/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://www.django-rest-framework.org//topics/release-notes/</loc>
|
||||
<lastmod>2016-09-29</lastmod>
|
||||
<lastmod>2016-10-14</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@
|
|||
<hr />
|
||||
<p><em>Below is an in-depth guide to the API changes and migration notes for 3.0.</em></p>
|
||||
<h2 id="request-objects"><a class="toclink" href="#request-objects">Request objects</a></h2>
|
||||
<h4 id="the-data-and-query_params-properties"><code>.query_params</code> properties.<a class="toclink" href="#the-data-and-query_params-properties">The <code>.data</code> and </a></h4>
|
||||
<h4 id="the-data-and-query_params-properties"><a class="toclink" href="#the-data-and-query_params-properties">The <code>.data</code> and <code>.query_params</code> properties.</a></h4>
|
||||
<p>The usage of <code>request.DATA</code> and <code>request.FILES</code> is now pending deprecation in favor of a single <code>request.data</code> attribute that contains <em>all</em> the parsed data.</p>
|
||||
<p>Having separate attributes is reasonable for web applications that only ever parse url-encoded or multipart requests, but makes less sense for the general-purpose request parsing that REST framework supports.</p>
|
||||
<p>You may now pass all the request data to a serializer class in a single argument:</p>
|
||||
|
@ -482,7 +482,7 @@ ExampleSerializer(data=request.DATA, files=request.FILES)
|
|||
<li>Calling <code>serializer.save()</code> then saves and returns the new object instance.</li>
|
||||
</ol>
|
||||
<p>The resulting API changes are further detailed below.</p>
|
||||
<h4 id="the-create-and-update-methods"><code>.update()</code> methods.<a class="toclink" href="#the-create-and-update-methods">The <code>.create()</code> and </a></h4>
|
||||
<h4 id="the-create-and-update-methods"><a class="toclink" href="#the-create-and-update-methods">The <code>.create()</code> and <code>.update()</code> methods.</a></h4>
|
||||
<p>The <code>.restore_object()</code> method is now removed, and we instead have two separate methods, <code>.create()</code> and <code>.update()</code>. These methods work slightly different to the previous <code>.restore_object()</code>.</p>
|
||||
<p>When using the <code>.create()</code> and <code>.update()</code> methods you should both create <em>and save</em> the object instance. This is in contrast to the previous <code>.restore_object()</code> behavior that would instantiate the object but not save it.</p>
|
||||
<p>These methods also replace the optional <code>.save_object()</code> method, which no longer exists.</p>
|
||||
|
@ -514,7 +514,7 @@ def create(self, validated_data):
|
|||
return Snippet.objects.create(**validated_data)
|
||||
</code></pre>
|
||||
<p>Note that these methods should return the newly created object instance.</p>
|
||||
<h4 id="use-validated_data-instead-of-object"><code>.object</code>.<a class="toclink" href="#use-validated_data-instead-of-object">Use <code>.validated_data</code> instead of </a></h4>
|
||||
<h4 id="use-validated_data-instead-of-object"><a class="toclink" href="#use-validated_data-instead-of-object">Use <code>.validated_data</code> instead of <code>.object</code>.</a></h4>
|
||||
<p>You must now use the <code>.validated_data</code> attribute if you need to inspect the data before saving, rather than using the <code>.object</code> attribute, which no longer exists.</p>
|
||||
<p>For example the following code <em>is no longer valid</em>:</p>
|
||||
<pre><code>if serializer.is_valid():
|
||||
|
@ -862,7 +862,7 @@ def all_high_scores(request):
|
|||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="serializer-fields"><a class="toclink" href="#serializer-fields">Serializer fields</a></h2>
|
||||
<h4 id="the-field-and-readonly-field-classes"><code>ReadOnly</code> field classes.<a class="toclink" href="#the-field-and-readonly-field-classes">The <code>Field</code> and </a></h4>
|
||||
<h4 id="the-field-and-readonly-field-classes"><a class="toclink" href="#the-field-and-readonly-field-classes">The <code>Field</code> and <code>ReadOnly</code> field classes.</a></h4>
|
||||
<p>There are some minor tweaks to the field base classes.</p>
|
||||
<p>Previously we had these two base classes:</p>
|
||||
<ul>
|
||||
|
@ -874,7 +874,7 @@ def all_high_scores(request):
|
|||
<li><code>Field</code> is the base class for all fields. It does not include any default implementation for either serializing or deserializing data.</li>
|
||||
<li><code>ReadOnlyField</code> is a concrete implementation for read-only fields that simply returns the attribute value without modification.</li>
|
||||
</ul>
|
||||
<h4 id="the-required-allow_null-allow_blank-and-default-arguments"><code>allow_null</code>, <code>default</code> arguments.<a class="toclink" href="#the-required-allow_null-allow_blank-and-default-arguments">The <code>required</code>, <code>allow_blank</code> and </a></h4>
|
||||
<h4 id="the-required-allow_null-allow_blank-and-default-arguments"><a class="toclink" href="#the-required-allow_null-allow_blank-and-default-arguments">The <code>required</code>, <code>allow_null</code>, <code>allow_blank</code> and <code>default</code> arguments.</a></h4>
|
||||
<p>REST framework now has more explicit and clear control over validating empty values for fields.</p>
|
||||
<p>Previously the meaning of the <code>required=False</code> keyword argument was underspecified. In practice its use meant that a field could either be not included in the input, or it could be included, but be <code>None</code> or the empty string.</p>
|
||||
<p>We now have a better separation, with separate <code>required</code>, <code>allow_null</code> and <code>allow_blank</code> arguments.</p>
|
||||
|
@ -984,7 +984,7 @@ This removes some magic and makes it easier and more obvious to move between imp
|
|||
<p>The following usage will <em>now raise an error</em>:</p>
|
||||
<pre><code>email = serializers.EmailField(source='email')
|
||||
</code></pre>
|
||||
<h4 id="the-uniquevalidator-and-uniquetogethervalidator-classes"><code>UniqueTogetherValidator</code> classes.<a class="toclink" href="#the-uniquevalidator-and-uniquetogethervalidator-classes">The <code>UniqueValidator</code> and </a></h4>
|
||||
<h4 id="the-uniquevalidator-and-uniquetogethervalidator-classes"><a class="toclink" href="#the-uniquevalidator-and-uniquetogethervalidator-classes">The <code>UniqueValidator</code> and <code>UniqueTogetherValidator</code> classes.</a></h4>
|
||||
<p>REST framework now provides new validators that allow you to ensure field uniqueness, while still using a completely explicit <code>Serializer</code> class instead of using <code>ModelSerializer</code>.</p>
|
||||
<p>The <code>UniqueValidator</code> should be applied to a serializer field, and takes a single <code>queryset</code> argument.</p>
|
||||
<pre><code>from rest_framework import serializers
|
||||
|
|
|
@ -482,17 +482,17 @@ documentation generation and parameter annotation.</p>
|
|||
<tr>
|
||||
<td><a href="http://www.coreapi.org/specification/encoding/#core-json-encoding">Core JSON</a></td>
|
||||
<td>Schema generation & client support.</td>
|
||||
<td>Built-in support in <code>coreapi</code></td>
|
||||
<td>Built-in support in <code>coreapi</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://openapis.org/specification">Swagger / OpenAPI</a></td>
|
||||
<td>Schema generation & client support.</td>
|
||||
<td>The <code>openapi-codec</code>package.</td>
|
||||
<td>The <code>openapi-codec</code> package.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://json-schema.org/latest/json-schema-hypermedia.html">JSON Hyper-Schema</a></td>
|
||||
<td>Currrently client support only.</td>
|
||||
<td>The <code>hyperschema-codec</code>package.</td>
|
||||
<td>The <code>hyperschema-codec</code> package.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://apiblueprint.org/">API Blueprint</a></td>
|
||||
|
|
|
@ -479,6 +479,7 @@
|
|||
<pre><code># Setup the virtual environment
|
||||
virtualenv env
|
||||
source env/bin/activate
|
||||
pip install django
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run the tests
|
||||
|
|
|
@ -581,22 +581,22 @@ class ProfileDetail(APIView):
|
|||
</tr>
|
||||
<tr>
|
||||
<td>select.html</td>
|
||||
<td><code>ChoiceField</code>or relational field types</td>
|
||||
<td><code>ChoiceField</code> or relational field types</td>
|
||||
<td>hide_label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>radio.html</td>
|
||||
<td><code>ChoiceField</code>or relational field types</td>
|
||||
<td><code>ChoiceField</code> or relational field types</td>
|
||||
<td>inline, hide_label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>select_multiple.html</td>
|
||||
<td><code>MultipleChoiceField</code>or relational fields with <code>many=True</code></td>
|
||||
<td><code>MultipleChoiceField</code> or relational fields with <code>many=True</code></td>
|
||||
<td>hide_label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>checkbox_multiple.html</td>
|
||||
<td><code>MultipleChoiceField</code>or relational fields with <code>many=True</code></td>
|
||||
<td><code>MultipleChoiceField</code> or relational fields with <code>many=True</code></td>
|
||||
<td>inline, hide_label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -611,7 +611,7 @@ class ProfileDetail(APIView):
|
|||
</tr>
|
||||
<tr>
|
||||
<td>list_fieldset.html</td>
|
||||
<td><code>ListField</code>or nested serializer with <code>many=True</code></td>
|
||||
<td><code>ListField</code> or nested serializer with <code>many=True</code></td>
|
||||
<td>hide_label</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -407,7 +407,7 @@
|
|||
<p>— Halford E. Luccock</p>
|
||||
</blockquote>
|
||||
<p>This document outlines our project management processes for REST framework.</p>
|
||||
<p>The aim is to ensure that the project has a high
|
||||
<p>The aim is to ensure that the project has a high
|
||||
<a href="http://en.wikipedia.org/wiki/Bus_factor">"bus factor"</a>, and can continue to remain well supported for the foreseeable future. Suggestions for improvements to our process are welcome.</p>
|
||||
<hr />
|
||||
<h2 id="maintenance-team"><a class="toclink" href="#maintenance-team">Maintenance team</a></h2>
|
||||
|
@ -540,7 +540,7 @@ tx push -s
|
|||
<h3 id="download-translations"><a class="toclink" href="#download-translations">Download translations</a></h3>
|
||||
<p>When a translator has finished translating their work needs to be downloaded from Transifex into the REST framework repository. To do this, run:</p>
|
||||
<pre><code># 3. Pull the translated django.po files from Transifex.
|
||||
tx pull -a
|
||||
tx pull -a --minimum-perc 10
|
||||
cd rest_framework
|
||||
# 4. Compile the binary .mo files for all supported languages.
|
||||
django-admin.py compilemessages
|
||||
|
|
|
@ -573,6 +573,7 @@ You probably want to also tag the version now:
|
|||
<ul>
|
||||
<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>
|
||||
</ul>
|
||||
<h3 id="misc"><a class="toclink" href="#misc">Misc</a></h3>
|
||||
<ul>
|
||||
|
|
|
@ -490,7 +490,7 @@ from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
|
|||
|
||||
|
||||
class SnippetSerializer(serializers.Serializer):
|
||||
pk = serializers.IntegerField(read_only=True)
|
||||
id = serializers.IntegerField(read_only=True)
|
||||
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
|
||||
code = serializers.CharField(style={'base_template': 'textarea.html'})
|
||||
linenos = serializers.BooleanField(required=False)
|
||||
|
@ -538,12 +538,12 @@ snippet.save()
|
|||
<p>We've now got a few snippet instances to play with. Let's take a look at serializing one of those instances.</p>
|
||||
<pre><code>serializer = SnippetSerializer(snippet)
|
||||
serializer.data
|
||||
# {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
|
||||
# {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
|
||||
</code></pre>
|
||||
<p>At this point we've translated the model instance into Python native datatypes. To finalize the serialization process we render the data into <code>json</code>.</p>
|
||||
<pre><code>content = JSONRenderer().render(serializer.data)
|
||||
content
|
||||
# '{"pk": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
|
||||
# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
|
||||
</code></pre>
|
||||
<p>Deserialization is similar. First we parse a stream into Python native datatypes...</p>
|
||||
<pre><code>from django.utils.six import BytesIO
|
||||
|
@ -564,7 +564,7 @@ serializer.save()
|
|||
<p>We can also serialize querysets instead of model instances. To do so we simply add a <code>many=True</code> flag to the serializer arguments.</p>
|
||||
<pre><code>serializer = SnippetSerializer(Snippet.objects.all(), many=True)
|
||||
serializer.data
|
||||
# [OrderedDict([('pk', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
|
||||
# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'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>
|
||||
|
@ -636,12 +636,12 @@ def snippet_list(request):
|
|||
<p>Note that because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as <code>csrf_exempt</code>. This isn't something that you'd normally want to do, and REST framework views actually use more sensible behavior than this, but it'll do for our purposes right now.</p>
|
||||
<p>We'll also need a view which corresponds to an individual snippet, and can be used to retrieve, update or delete the snippet.</p>
|
||||
<pre><code>@csrf_exempt
|
||||
def snippet_detail(request, pk):
|
||||
def snippet_detail(request, id):
|
||||
"""
|
||||
Retrieve, update or delete a code snippet.
|
||||
"""
|
||||
try:
|
||||
snippet = Snippet.objects.get(pk=pk)
|
||||
snippet = Snippet.objects.get(id=id)
|
||||
except Snippet.DoesNotExist:
|
||||
return HttpResponse(status=404)
|
||||
|
||||
|
@ -667,7 +667,7 @@ from snippets import views
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^snippets/$', views.snippet_list),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
|
||||
url(r'^snippets/(?P<id>[0-9]+)/$', views.snippet_detail),
|
||||
]
|
||||
</code></pre>
|
||||
<p>We also need to wire up the root urlconf, in the <code>tutorial/urls.py</code> file, to include our snippet app's URLs.</p>
|
||||
|
|
|
@ -465,12 +465,12 @@ def snippet_list(request):
|
|||
<p>Our instance view is an improvement over the previous example. It's a little more concise, and the code now feels very similar to if we were working with the Forms API. We're also using named status codes, which makes the response meanings more obvious.</p>
|
||||
<p>Here is the view for an individual snippet, in the <code>views.py</code> module.</p>
|
||||
<pre><code>@api_view(['GET', 'PUT', 'DELETE'])
|
||||
def snippet_detail(request, pk):
|
||||
def snippet_detail(request, id):
|
||||
"""
|
||||
Retrieve, update or delete a snippet instance.
|
||||
"""
|
||||
try:
|
||||
snippet = Snippet.objects.get(pk=pk)
|
||||
snippet = Snippet.objects.get(id=id)
|
||||
except Snippet.DoesNotExist:
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
@ -497,7 +497,7 @@ def snippet_detail(request, pk):
|
|||
<pre><code>def snippet_list(request, format=None):
|
||||
</code></pre>
|
||||
<p>and</p>
|
||||
<pre><code>def snippet_detail(request, pk, format=None):
|
||||
<pre><code>def snippet_detail(request, id, format=None):
|
||||
</code></pre>
|
||||
<p>Now update the <code>urls.py</code> file slightly, to append a set of <code>format_suffix_patterns</code> in addition to the existing URLs.</p>
|
||||
<pre><code>from django.conf.urls import url
|
||||
|
@ -506,7 +506,7 @@ from snippets import views
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^snippets/$', views.snippet_list),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),
|
||||
url(r'^snippets/(?P<id>[0-9]+)$', views.snippet_detail),
|
||||
]
|
||||
|
||||
urlpatterns = format_suffix_patterns(urlpatterns)
|
||||
|
|
|
@ -426,27 +426,27 @@ class SnippetList(APIView):
|
|||
"""
|
||||
Retrieve, update or delete a snippet instance.
|
||||
"""
|
||||
def get_object(self, pk):
|
||||
def get_object(self, id):
|
||||
try:
|
||||
return Snippet.objects.get(pk=pk)
|
||||
return Snippet.objects.get(id=id)
|
||||
except Snippet.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
def get(self, request, pk, format=None):
|
||||
snippet = self.get_object(pk)
|
||||
def get(self, request, id, format=None):
|
||||
snippet = self.get_object(id)
|
||||
serializer = SnippetSerializer(snippet)
|
||||
return Response(serializer.data)
|
||||
|
||||
def put(self, request, pk, format=None):
|
||||
snippet = self.get_object(pk)
|
||||
def put(self, request, id, format=None):
|
||||
snippet = self.get_object(id)
|
||||
serializer = SnippetSerializer(snippet, data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def delete(self, request, pk, format=None):
|
||||
snippet = self.get_object(pk)
|
||||
def delete(self, request, id, format=None):
|
||||
snippet = self.get_object(id)
|
||||
snippet.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
</code></pre>
|
||||
|
@ -458,7 +458,7 @@ from snippets import views
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^snippets/$', views.SnippetList.as_view()),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
|
||||
url(r'^snippets/(?P<id>[0-9]+)/$', views.SnippetDetail.as_view()),
|
||||
]
|
||||
|
||||
urlpatterns = format_suffix_patterns(urlpatterns)
|
||||
|
|
|
@ -492,7 +492,7 @@ class UserDetail(generics.RetrieveAPIView):
|
|||
</code></pre>
|
||||
<p>Finally we need to add those views into the API, by referencing them from the URL conf. Add the following to the patterns in <code>urls.py</code>.</p>
|
||||
<pre><code>url(r'^users/$', views.UserList.as_view()),
|
||||
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
|
||||
url(r'^users/(?P<id>[0-9]+)/$', views.UserDetail.as_view()),
|
||||
</code></pre>
|
||||
<h2 id="associating-snippets-with-users"><a class="toclink" href="#associating-snippets-with-users">Associating Snippets with Users</a></h2>
|
||||
<p>Right now, if we created a code snippet, there'd be no way of associating the user that created the snippet, with the snippet instance. The user isn't sent as part of the serialized representation, but is instead a property of the incoming request.</p>
|
||||
|
@ -532,7 +532,7 @@ url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
|
|||
</code></pre>
|
||||
<p>The <code>r'^api-auth/'</code> part of pattern can actually be whatever URL you want to use. The only restriction is that the included urls must use the <code>'rest_framework'</code> namespace. In Django 1.9+, REST framework will set the namespace, so you may leave it out.</p>
|
||||
<p>Now if you open up the browser again and refresh the page you'll see a 'Login' link in the top right of the page. If you log in as one of the users you created earlier, you'll be able to create code snippets again.</p>
|
||||
<p>Once you've created a few code snippets, navigate to the '/users/' endpoint, and notice that the representation includes a list of the snippet pks that are associated with each user, in each user's 'snippets' field.</p>
|
||||
<p>Once you've created a few code snippets, navigate to the '/users/' endpoint, and notice that the representation includes a list of the snippet ids that are associated with each user, in each user's 'snippets' field.</p>
|
||||
<h2 id="object-level-permissions"><a class="toclink" href="#object-level-permissions">Object level permissions</a></h2>
|
||||
<p>Really we'd like all code snippets to be visible to anyone, but also make sure that only the user that created a code snippet is able to update or delete it.</p>
|
||||
<p>To do that we're going to need to create a custom permission.</p>
|
||||
|
|
|
@ -443,7 +443,7 @@ We'll add a url pattern for our new API root in <code>snippets/urls.py</code>:</
|
|||
<pre><code>url(r'^$', views.api_root),
|
||||
</code></pre>
|
||||
<p>And then add a url pattern for the snippet highlights:</p>
|
||||
<pre><code>url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
|
||||
<pre><code>url(r'^snippets/(?P<id>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
|
||||
</code></pre>
|
||||
<h2 id="hyperlinking-our-api"><a class="toclink" href="#hyperlinking-our-api">Hyperlinking our API</a></h2>
|
||||
<p>Dealing with relationships between entities is one of the more challenging aspects of Web API design. There are a number of different ways that we might choose to represent a relationship:</p>
|
||||
|
@ -459,7 +459,7 @@ We'll add a url pattern for our new API root in <code>snippets/urls.py</code>:</
|
|||
<p>In this case we'd like to use a hyperlinked style between entities. In order to do so, we'll modify our serializers to extend <code>HyperlinkedModelSerializer</code> instead of the existing <code>ModelSerializer</code>.</p>
|
||||
<p>The <code>HyperlinkedModelSerializer</code> has the following differences from <code>ModelSerializer</code>:</p>
|
||||
<ul>
|
||||
<li>It does not include the <code>pk</code> field by default.</li>
|
||||
<li>It does not include the <code>id</code> field by default.</li>
|
||||
<li>It includes a <code>url</code> field, using <code>HyperlinkedIdentityField</code>.</li>
|
||||
<li>Relationships use <code>HyperlinkedRelatedField</code>,
|
||||
instead of <code>PrimaryKeyRelatedField</code>.</li>
|
||||
|
@ -471,7 +471,7 @@ We'll add a url pattern for our new API root in <code>snippets/urls.py</code>:</
|
|||
|
||||
class Meta:
|
||||
model = Snippet
|
||||
fields = ('url', 'pk', 'highlight', 'owner',
|
||||
fields = ('url', 'id', 'highlight', 'owner',
|
||||
'title', 'code', 'linenos', 'language', 'style')
|
||||
|
||||
|
||||
|
@ -480,7 +480,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('url', 'pk', 'username', 'snippets')
|
||||
fields = ('url', 'id', 'username', 'snippets')
|
||||
</code></pre>
|
||||
<p>Notice that we've also added a new <code>'highlight'</code> field. This field is of the same type as the <code>url</code> field, except that it points to the <code>'snippet-highlight'</code> url pattern, instead of the <code>'snippet-detail'</code> url pattern.</p>
|
||||
<p>Because we've included format suffixed URLs such as <code>'.json'</code>, we also need to indicate on the <code>highlight</code> field that any format suffixed hyperlinks it returns should use the <code>'.html'</code> suffix.</p>
|
||||
|
@ -503,16 +503,16 @@ urlpatterns = format_suffix_patterns([
|
|||
url(r'^snippets/$',
|
||||
views.SnippetList.as_view(),
|
||||
name='snippet-list'),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/$',
|
||||
url(r'^snippets/(?P<id>[0-9]+)/$',
|
||||
views.SnippetDetail.as_view(),
|
||||
name='snippet-detail'),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$',
|
||||
url(r'^snippets/(?P<id>[0-9]+)/highlight/$',
|
||||
views.SnippetHighlight.as_view(),
|
||||
name='snippet-highlight'),
|
||||
url(r'^users/$',
|
||||
views.UserList.as_view(),
|
||||
name='user-list'),
|
||||
url(r'^users/(?P<pk>[0-9]+)/$',
|
||||
url(r'^users/(?P<id>[0-9]+)/$',
|
||||
views.UserDetail.as_view(),
|
||||
name='user-detail')
|
||||
])
|
||||
|
|
|
@ -473,10 +473,10 @@ user_detail = UserViewSet.as_view({
|
|||
<pre><code>urlpatterns = format_suffix_patterns([
|
||||
url(r'^$', api_root),
|
||||
url(r'^snippets/$', snippet_list, name='snippet-list'),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),
|
||||
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
|
||||
url(r'^snippets/(?P<id>[0-9]+)/$', snippet_detail, name='snippet-detail'),
|
||||
url(r'^snippets/(?P<id>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
|
||||
url(r'^users/$', user_list, name='user-list'),
|
||||
url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail')
|
||||
url(r'^users/(?P<id>[0-9]+)/$', user_detail, name='user-detail')
|
||||
])
|
||||
</code></pre>
|
||||
<h2 id="using-routers"><a class="toclink" href="#using-routers">Using Routers</a></h2>
|
||||
|
|
|
@ -429,16 +429,23 @@ we can simply use the automatic schema generation.</p>
|
|||
API schema.</p>
|
||||
<pre><code>$ pip install coreapi
|
||||
</code></pre>
|
||||
<p>We can now include a schema for our API, by adding a <code>schema_title</code> argument to
|
||||
the router instantiation.</p>
|
||||
<pre><code>router = DefaultRouter(schema_title='Pastebin API')
|
||||
<p>We can now include a schema for our API, by including an autogenerated schema
|
||||
view in our URL configuration.</p>
|
||||
<pre><code>from rest_framework.schemas import get_schema_view
|
||||
|
||||
schema_view = get_schema_view(title='Pastebin API')
|
||||
|
||||
urlpatterns = [
|
||||
url('^schema/$', schema_view),
|
||||
...
|
||||
]
|
||||
</code></pre>
|
||||
<p>If you visit the API root 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/ Accept:application/vnd.coreapi+json
|
||||
<pre><code>$ http http://127.0.0.1:8000/schema/ Accept:application/vnd.coreapi+json
|
||||
HTTP/1.0 200 OK
|
||||
Allow: GET, HEAD, OPTIONS
|
||||
Content-Type: application/vnd.coreapi+json
|
||||
|
@ -476,16 +483,16 @@ 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/
|
||||
<Pastebin API "http://127.0.0.1:8000/">
|
||||
<pre><code>$ coreapi get http://127.0.0.1:8000/schema/
|
||||
<Pastebin API "http://127.0.0.1:8000/schema/">
|
||||
snippets: {
|
||||
highlight(pk)
|
||||
highlight(id)
|
||||
list()
|
||||
retrieve(pk)
|
||||
read(id)
|
||||
}
|
||||
users: {
|
||||
list()
|
||||
retrieve(pk)
|
||||
read(id)
|
||||
}
|
||||
</code></pre>
|
||||
<p>We haven't authenticated yet, so right now we're only able to see the read only
|
||||
|
@ -495,7 +502,7 @@ endpoints, in line with how we've set up the permissions on the API.</p>
|
|||
[
|
||||
{
|
||||
"url": "http://127.0.0.1:8000/snippets/1/",
|
||||
"pk": 1,
|
||||
"id": 1,
|
||||
"highlight": "http://127.0.0.1:8000/snippets/1/highlight/",
|
||||
"owner": "lucy",
|
||||
"title": "Example",
|
||||
|
@ -508,7 +515,7 @@ endpoints, in line with how we've set up the permissions on the API.</p>
|
|||
</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 pk=1
|
||||
<pre><code>$ coreapi action snippets highlight --param id=1
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
|
||||
<html>
|
||||
|
@ -528,19 +535,19 @@ Added credentials
|
|||
<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/">
|
||||
Pastebin API "http://127.0.0.1:8000/schema/">
|
||||
snippets: {
|
||||
create(code, [title], [linenos], [language], [style])
|
||||
destroy(pk)
|
||||
highlight(pk)
|
||||
delete(id)
|
||||
highlight(id)
|
||||
list()
|
||||
partial_update(pk, [title], [code], [linenos], [language], [style])
|
||||
retrieve(pk)
|
||||
update(pk, code, [title], [linenos], [language], [style])
|
||||
partial_update(id, [title], [code], [linenos], [language], [style])
|
||||
read(id)
|
||||
update(id, code, [title], [linenos], [language], [style])
|
||||
}
|
||||
users: {
|
||||
list()
|
||||
retrieve(pk)
|
||||
read(id)
|
||||
}
|
||||
</code></pre>
|
||||
<p>We're now able to interact with these endpoints. For example, to create a new
|
||||
|
@ -548,7 +555,7 @@ 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/",
|
||||
"pk": 7,
|
||||
"id": 7,
|
||||
"highlight": "http://127.0.0.1:8000/snippets/7/highlight/",
|
||||
"owner": "lucy",
|
||||
"title": "Example",
|
||||
|
@ -559,7 +566,7 @@ snippet:</p>
|
|||
}
|
||||
</code></pre>
|
||||
<p>And to delete a snippet:</p>
|
||||
<pre><code>$ coreapi action snippets destroy --param pk=7
|
||||
<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
|
||||
|
|
Loading…
Reference in New Issue
Block a user