django-rest-framework/docs/api-guide/views.md

228 lines
8.6 KiB
Markdown
Raw Normal View History

2019-07-01 05:04:36 +03:00
---
source:
- decorators.py
- views.py
---
2012-09-09 01:06:13 +04:00
# Class-based Views
2012-09-09 01:13:11 +04:00
> Django's class-based views are a welcome departure from the old-style views.
2012-09-01 23:26:27 +04:00
>
> — [Reinout van Rees][cite]
2012-09-27 00:47:19 +04:00
REST framework provides an `APIView` class, which subclasses Django's `View` class.
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
`APIView` classes are different from regular `View` classes in the following ways:
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
* Requests passed to the handler methods will be REST framework's `Request` instances, not Django's `HttpRequest` instances.
* Handler methods may return REST framework's `Response`, instead of Django's `HttpResponse`. The view will manage content negotiation and setting the correct renderer on the response.
* Any `APIException` exceptions will be caught and mediated into appropriate responses.
* Incoming requests will be authenticated and appropriate permission and/or throttle checks will be run before dispatching the request to the handler method.
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
Using the `APIView` class is pretty much the same as using a regular `View` class, as usual, the incoming request is dispatched to an appropriate handler method such as `.get()` or `.post()`. Additionally, a number of attributes may be set on the class that control various aspects of the API policy.
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
For example:
2012-11-27 21:42:37 +04:00
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
from django.contrib.auth.models import User
2012-09-27 00:47:19 +04:00
class ListUsers(APIView):
"""
View to list all users in the system.
2012-09-27 00:47:19 +04:00
* Requires token authentication.
* Only admin users are able to access this view.
"""
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [permissions.IsAdminUser]
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
def get(self, request, format=None):
"""
Return a list of all users.
"""
2012-10-17 18:41:57 +04:00
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
2012-09-01 23:26:27 +04:00
---
**Note**: The full methods, attributes on, and relations between Django REST Framework's `APIView`, `GenericAPIView`, various `Mixins`, and `Viewsets` can be initially complex. In addition to the documentation here, the [Classy Django REST Framework][classy-drf] resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views.
---
2012-09-27 00:47:19 +04:00
## API policy attributes
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
The following attributes control the pluggable aspects of API views.
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
### .renderer_classes
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
### .parser_classes
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
### .authentication_classes
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
### .throttle_classes
2012-09-01 23:26:27 +04:00
2012-09-27 00:47:19 +04:00
### .permission_classes
### .content_negotiation_class
2012-09-27 00:47:19 +04:00
## API policy instantiation methods
The following methods are used by REST framework to instantiate the various pluggable API policies. You won't typically need to override these methods.
### .get_renderers(self)
### .get_parsers(self)
### .get_authenticators(self)
### .get_throttles(self)
### .get_permissions(self)
### .get_content_negotiator(self)
### .get_exception_handler(self)
2012-09-27 00:47:19 +04:00
## API policy implementation methods
The following methods are called before dispatching to the handler method.
### .check_permissions(self, request)
2012-09-27 00:47:19 +04:00
### .check_throttles(self, request)
2012-09-27 00:47:19 +04:00
### .perform_content_negotiation(self, request, force=False)
2012-09-27 00:47:19 +04:00
## Dispatch methods
The following methods are called directly by the view's `.dispatch()` method.
2013-01-17 15:17:53 +04:00
These perform any actions that need to occur before or after calling the handler methods such as `.get()`, `.post()`, `put()`, `patch()` and `.delete()`.
2012-09-27 00:47:19 +04:00
2012-10-05 18:22:30 +04:00
### .initial(self, request, \*args, **kwargs)
2012-09-27 00:47:19 +04:00
Performs any actions that need to occur before the handler method gets called.
This method is used to enforce permissions and throttling, and perform content negotiation.
You won't typically need to override this method.
### .handle_exception(self, exc)
Any exception thrown by the handler method will be passed to this method, which either returns a `Response` instance, or re-raises the exception.
The default implementation handles any subclass of `rest_framework.exceptions.APIException`, as well as Django's `Http404` and `PermissionDenied` exceptions, and returns an appropriate error response.
If you need to customize the error responses your API returns you should subclass this method.
2012-10-05 18:22:30 +04:00
### .initialize_request(self, request, \*args, **kwargs)
2012-09-27 00:47:19 +04:00
Ensures that the request object that is passed to the handler method is an instance of `Request`, rather than the usual Django `HttpRequest`.
You won't typically need to override this method.
2012-10-05 18:22:30 +04:00
### .finalize_response(self, request, response, \*args, **kwargs)
2012-09-27 00:47:19 +04:00
2013-08-07 22:00:06 +04:00
Ensures that any `Response` object returned from the handler method will be rendered into the correct content type, as determined by the content negotiation.
2012-09-27 00:47:19 +04:00
You won't typically need to override this method.
2012-09-01 23:26:27 +04:00
2012-10-02 14:48:25 +04:00
---
2012-10-02 14:04:06 +04:00
# Function Based Views
> Saying [that class-based views] is always the superior solution is a mistake.
2012-10-02 14:04:06 +04:00
>
> — [Nick Coghlan][cite2]
2013-05-28 19:13:12 +04:00
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 `Request` (rather than the usual Django `HttpRequest`) and allows them to return a `Response` (instead of a Django `HttpResponse`), and allow you to configure how the request is processed.
2012-10-27 21:39:17 +04:00
## @api_view()
**Signature:** `@api_view(http_method_names=['GET'])`
2014-11-28 18:55:02 +03:00
The core of this functionality is the `api_view` 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:
from rest_framework.decorators import api_view
2021-10-07 17:52:44 +03:00
from rest_framework.response import Response
2014-11-28 18:55:02 +03:00
@api_view()
def hello_world(request):
return Response({"message": "Hello, world!"})
2013-07-10 21:02:38 +04:00
This view will use the default renderers, parsers, authentication classes etc specified in the [settings].
Version 3.5 (#4525) * Start test case * Added 'requests' test client * Address typos * Graceful fallback if requests is not installed. * Add cookie support * Tests for auth and CSRF * Py3 compat * py3 compat * py3 compat * Add get_requests_client * Added SchemaGenerator.should_include_link * add settings for html cutoff on related fields * Router doesn't work if prefix is blank, though project urls.py handles prefix * Fix Django 1.10 to-many deprecation * Add django.core.urlresolvers compatibility * Update django-filter & django-guardian * Check for empty router prefix; adjust URL accordingly It's easiest to fix this issue after we have made the regex. To try to fix it before would require doing something different for List vs Detail, which means we'd have to know which type of url we're constructing before acting accordingly. * Fix misc django deprecations * Use TOC extension instead of header * Fix deprecations for py3k * Add py3k compatibility to is_simple_callable * Add is_simple_callable tests * Drop python 3.2 support (EOL, Dropped by Django) * schema_renderers= should *set* the renderers, not append to them. * API client (#4424) * Fix release notes * Add note about 'User account is disabled.' vs 'Unable to log in' * Clean up schema generation (#4527) * Handle multiple methods on custom action (#4529) * RequestsClient, CoreAPIClient * exclude_from_schema * Added 'get_schema_view()' shortcut * Added schema descriptions * Better descriptions for schemas * Add type annotation to schema generation * Coerce schema 'pk' in path to actual field name * Deprecations move into assertion errors * Use get_schema_view in tests * Updte CoreJSON media type * Handle schema structure correctly when path prefixs exist. Closes #4401 * Add PendingDeprecation to Router schema generation. * Added SCHEMA_COERCE_PATH_PK and SCHEMA_COERCE_METHOD_NAMES * Renamed and documented 'get_schema_fields' interface.
2016-10-10 15:03:46 +03:00
By default only `GET` 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:
2014-11-28 18:55:02 +03:00
@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!"})
Version 3.5 (#4525) * Start test case * Added 'requests' test client * Address typos * Graceful fallback if requests is not installed. * Add cookie support * Tests for auth and CSRF * Py3 compat * py3 compat * py3 compat * Add get_requests_client * Added SchemaGenerator.should_include_link * add settings for html cutoff on related fields * Router doesn't work if prefix is blank, though project urls.py handles prefix * Fix Django 1.10 to-many deprecation * Add django.core.urlresolvers compatibility * Update django-filter & django-guardian * Check for empty router prefix; adjust URL accordingly It's easiest to fix this issue after we have made the regex. To try to fix it before would require doing something different for List vs Detail, which means we'd have to know which type of url we're constructing before acting accordingly. * Fix misc django deprecations * Use TOC extension instead of header * Fix deprecations for py3k * Add py3k compatibility to is_simple_callable * Add is_simple_callable tests * Drop python 3.2 support (EOL, Dropped by Django) * schema_renderers= should *set* the renderers, not append to them. * API client (#4424) * Fix release notes * Add note about 'User account is disabled.' vs 'Unable to log in' * Clean up schema generation (#4527) * Handle multiple methods on custom action (#4529) * RequestsClient, CoreAPIClient * exclude_from_schema * Added 'get_schema_view()' shortcut * Added schema descriptions * Better descriptions for schemas * Add type annotation to schema generation * Coerce schema 'pk' in path to actual field name * Deprecations move into assertion errors * Use get_schema_view in tests * Updte CoreJSON media type * Handle schema structure correctly when path prefixs exist. Closes #4401 * Add PendingDeprecation to Router schema generation. * Added SCHEMA_COERCE_PATH_PK and SCHEMA_COERCE_METHOD_NAMES * Renamed and documented 'get_schema_fields' interface.
2016-10-10 15:03:46 +03:00
2012-10-27 21:39:17 +04:00
## API policy decorators
2013-07-10 21:02:38 +04:00
To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come *after* (below) the `@api_view` decorator. For example, to create a view that uses a [throttle][throttling] to ensure it can only be called once per day by a particular user, use the `@throttle_classes` decorator, passing a list of throttle classes:
from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle
class OncePerDayUserThrottle(UserRateThrottle):
2020-09-16 16:43:27 +03:00
rate = '1/day'
@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
return Response({"message": "Hello for today! See you tomorrow!"})
These decorators correspond to the attributes set on `APIView` subclasses, described above.
2012-10-27 21:39:17 +04:00
The available decorators are:
2012-10-27 21:39:17 +04:00
* `@renderer_classes(...)`
* `@parser_classes(...)`
* `@authentication_classes(...)`
* `@throttle_classes(...)`
* `@permission_classes(...)`
2012-10-02 14:04:06 +04:00
2012-10-27 21:39:17 +04:00
Each of these decorators takes a single argument which must be a list or tuple of classes.
2012-10-02 14:04:06 +04:00
## View schema decorator
To override the default schema generation for function based views you may use
the `@schema` decorator. This must come *after* (below) the `@api_view`
decorator. For example:
from rest_framework.decorators import api_view, schema
from rest_framework.schemas import AutoSchema
class CustomAutoSchema(AutoSchema):
def get_link(self, path, method, base_url):
# override view introspection here...
@api_view(['GET'])
@schema(CustomAutoSchema())
def view(request):
return Response({"message": "Hello for today! See you tomorrow!"})
This decorator takes a single `AutoSchema` instance, an `AutoSchema` subclass
instance or `ManualSchema` instance as described in the [Schemas documentation][schemas].
You may pass `None` in order to exclude the view from schema generation.
@api_view(['GET'])
@schema(None)
def view(request):
return Response({"message": "Will not appear in schema!"})
[cite]: https://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html
[cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html
2013-12-05 04:10:05 +04:00
[settings]: settings.md
[throttling]: throttling.md
Version 3.5 (#4525) * Start test case * Added 'requests' test client * Address typos * Graceful fallback if requests is not installed. * Add cookie support * Tests for auth and CSRF * Py3 compat * py3 compat * py3 compat * Add get_requests_client * Added SchemaGenerator.should_include_link * add settings for html cutoff on related fields * Router doesn't work if prefix is blank, though project urls.py handles prefix * Fix Django 1.10 to-many deprecation * Add django.core.urlresolvers compatibility * Update django-filter & django-guardian * Check for empty router prefix; adjust URL accordingly It's easiest to fix this issue after we have made the regex. To try to fix it before would require doing something different for List vs Detail, which means we'd have to know which type of url we're constructing before acting accordingly. * Fix misc django deprecations * Use TOC extension instead of header * Fix deprecations for py3k * Add py3k compatibility to is_simple_callable * Add is_simple_callable tests * Drop python 3.2 support (EOL, Dropped by Django) * schema_renderers= should *set* the renderers, not append to them. * API client (#4424) * Fix release notes * Add note about 'User account is disabled.' vs 'Unable to log in' * Clean up schema generation (#4527) * Handle multiple methods on custom action (#4529) * RequestsClient, CoreAPIClient * exclude_from_schema * Added 'get_schema_view()' shortcut * Added schema descriptions * Better descriptions for schemas * Add type annotation to schema generation * Coerce schema 'pk' in path to actual field name * Deprecations move into assertion errors * Use get_schema_view in tests * Updte CoreJSON media type * Handle schema structure correctly when path prefixs exist. Closes #4401 * Add PendingDeprecation to Router schema generation. * Added SCHEMA_COERCE_PATH_PK and SCHEMA_COERCE_METHOD_NAMES * Renamed and documented 'get_schema_fields' interface.
2016-10-10 15:03:46 +03:00
[schemas]: schemas.md
[classy-drf]: http://www.cdrf.co