mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-08 06:14:47 +03:00
Merge 1f635ca342
into 2e85b4ec3c
This commit is contained in:
commit
ef98c23fe1
|
@ -150,7 +150,7 @@ Similar to `DjangoModelPermissions`, but also allows unauthenticated users to ha
|
|||
|
||||
This permission class ties into Django's standard [object permissions framework][objectpermissions] that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as [django-guardian][guardian].
|
||||
|
||||
As with `DjangoModelPermissions`, this permission must only be applied to views that have a `.queryset` property. Authorization will only be granted if the user *is authenticated* and has the *relevant per-object permissions* and *relevant model permissions* assigned.
|
||||
As with `DjangoModelPermissions`, this permission must only be applied to views that have a `.queryset` property or `.get_queryset()` method. Authorization will only be granted if the user *is authenticated* and has the *relevant per-object permissions* and *relevant model permissions* assigned.
|
||||
|
||||
* `POST` requests require the user to have the `add` permission on the model instance.
|
||||
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model instance.
|
||||
|
|
|
@ -3,6 +3,7 @@ Provides a set of pluggable permission policies.
|
|||
"""
|
||||
from __future__ import unicode_literals
|
||||
from django.http import Http404
|
||||
from django.utils import six
|
||||
from rest_framework.compat import get_model_name
|
||||
|
||||
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
|
||||
|
@ -109,8 +110,6 @@ class DjangoModelPermissions(BasePermission):
|
|||
def has_permission(self, request, view):
|
||||
try:
|
||||
queryset = view.get_queryset()
|
||||
except AttributeError:
|
||||
queryset = getattr(view, 'queryset', None)
|
||||
except AssertionError:
|
||||
# view.get_queryset() didn't find .queryset
|
||||
queryset = None
|
||||
|
@ -172,7 +171,14 @@ class DjangoObjectPermissions(DjangoModelPermissions):
|
|||
return [perm % kwargs for perm in self.perms_map[method]]
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
model_cls = view.queryset.model
|
||||
try:
|
||||
queryset = view.get_queryset()
|
||||
except AssertionError as exc:
|
||||
# view.get_queryset() didn't find .queryset
|
||||
raise six.raise_from(AssertionError(
|
||||
'Cannot apply DjangoObjectPermissions on a view that '
|
||||
'does not have `.queryset` property nor redefines `.get_queryset()`.'), exc)
|
||||
model_cls = queryset.model
|
||||
user = request.user
|
||||
|
||||
perms = self.get_required_object_permissions(request.method, model_cls)
|
||||
|
|
|
@ -227,6 +227,18 @@ class ObjectPermissionListView(generics.ListAPIView):
|
|||
object_permissions_list_view = ObjectPermissionListView.as_view()
|
||||
|
||||
|
||||
class GetQuerysetObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):
|
||||
serializer_class = BasicPermSerializer
|
||||
authentication_classes = [authentication.BasicAuthentication]
|
||||
permission_classes = [ViewObjectPermissions]
|
||||
|
||||
def get_queryset(self):
|
||||
return BasicPermModel.objects.all()
|
||||
|
||||
|
||||
get_queryset_object_permissions_view = GetQuerysetObjectPermissionInstanceView.as_view()
|
||||
|
||||
|
||||
@unittest.skipUnless(guardian, 'django-guardian not installed')
|
||||
class ObjectPermissionsIntegrationTests(TestCase):
|
||||
"""
|
||||
|
@ -326,6 +338,15 @@ class ObjectPermissionsIntegrationTests(TestCase):
|
|||
response = object_permissions_view(request, pk='1')
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def test_can_read_get_queryset_permissions(self):
|
||||
"""
|
||||
same as ``test_can_read_permissions`` but with a view
|
||||
that rely on ``.get_queryset()`` instead of ``.queryset``.
|
||||
"""
|
||||
request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['readonly'])
|
||||
response = get_queryset_object_permissions_view(request, pk='1')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
# Read list
|
||||
def test_can_read_list_permissions(self):
|
||||
request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['readonly'])
|
||||
|
|
Loading…
Reference in New Issue
Block a user