mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 05:04:31 +03:00
PUT as create docs, and move mixin out to external gist
This commit is contained in:
parent
37845968cd
commit
d27b8cc09b
|
@ -368,6 +368,20 @@ If you are using a mixin across multiple views, you can take this a step further
|
||||||
|
|
||||||
Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.
|
Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PUT as create
|
||||||
|
|
||||||
|
Prior to version 3.0 the REST framework mixins treated `PUT` as either an update or a create operation, depending on if the object already existed or not.
|
||||||
|
|
||||||
|
Allowing `PUT` as create operations is problematic, as it necessarily exposes information about the existence or non-existance of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning `404` responses.
|
||||||
|
|
||||||
|
Both styles "`PUT` as 404" and "`PUT` as create" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.
|
||||||
|
|
||||||
|
If you need to generic PUT-as-create behavior you may want to include something like [this `AllowPUTAsCreateMixin` class](https://gist.github.com/tomchristie/a2ace4577eff2c603b1b) as a mixin to your views.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Third party packages
|
# Third party packages
|
||||||
|
|
||||||
The following third party packages provide additional generic view implementations.
|
The following third party packages provide additional generic view implementations.
|
||||||
|
|
|
@ -694,7 +694,7 @@ Allowing `PUT` as create operations is problematic, as it necessarily exposes in
|
||||||
|
|
||||||
Both styles "`PUT` as 404" and "`PUT` as create" can be valid in different circumstances, but we've now opted for the 404 behavior as the default, due to it being simpler and more obvious.
|
Both styles "`PUT` as 404" and "`PUT` as create" can be valid in different circumstances, but we've now opted for the 404 behavior as the default, due to it being simpler and more obvious.
|
||||||
|
|
||||||
If you need to restore the previous behavior you can include the `AllowPUTAsCreateMixin` class in your view. This class can be imported from `rest_framework.mixins`.
|
If you need to restore the previous behavior you may want to include [this `AllowPUTAsCreateMixin` class](https://gist.github.com/tomchristie/a2ace4577eff2c603b1b) as a mixin to your views.
|
||||||
|
|
||||||
#### Customizing error responses.
|
#### Customizing error responses.
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,8 @@ which allows mixin classes to be composed in interesting ways.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.http import Http404
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.request import clone_request
|
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,49 +87,3 @@ class DestroyModelMixin(object):
|
||||||
|
|
||||||
def perform_destroy(self, instance):
|
def perform_destroy(self, instance):
|
||||||
instance.delete()
|
instance.delete()
|
||||||
|
|
||||||
|
|
||||||
# The AllowPUTAsCreateMixin was previously the default behaviour
|
|
||||||
# for PUT requests. This has now been removed and must be *explicitly*
|
|
||||||
# included if it is the behavior that you want.
|
|
||||||
# For more info see: ...
|
|
||||||
|
|
||||||
class AllowPUTAsCreateMixin(object):
|
|
||||||
"""
|
|
||||||
The following mixin class may be used in order to support PUT-as-create
|
|
||||||
behavior for incoming requests.
|
|
||||||
"""
|
|
||||||
def update(self, request, *args, **kwargs):
|
|
||||||
partial = kwargs.pop('partial', False)
|
|
||||||
instance = self.get_object_or_none()
|
|
||||||
serializer = self.get_serializer(instance, data=request.data, partial=partial)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
if instance is None:
|
|
||||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
|
||||||
lookup_value = self.kwargs[lookup_url_kwarg]
|
|
||||||
extra_kwargs = {self.lookup_field: lookup_value}
|
|
||||||
serializer.save(**extra_kwargs)
|
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
||||||
|
|
||||||
serializer.save()
|
|
||||||
return Response(serializer.data)
|
|
||||||
|
|
||||||
def partial_update(self, request, *args, **kwargs):
|
|
||||||
kwargs['partial'] = True
|
|
||||||
return self.update(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_object_or_none(self):
|
|
||||||
try:
|
|
||||||
return self.get_object()
|
|
||||||
except Http404:
|
|
||||||
if self.request.method == 'PUT':
|
|
||||||
# For PUT-as-create operation, we need to ensure that we have
|
|
||||||
# relevant permissions, as if this was a POST request. This
|
|
||||||
# will either raise a PermissionDenied exception, or simply
|
|
||||||
# return None.
|
|
||||||
self.check_permissions(clone_request(self.request, 'POST'))
|
|
||||||
else:
|
|
||||||
# PATCH requests where the object does not exist should still
|
|
||||||
# return a 404 response.
|
|
||||||
raise
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user