Neater override hooks and more docs for DjangoModelPermissions.

Refs #702.
This commit is contained in:
Tom Christie 2013-03-08 23:42:20 +00:00
parent 6c1fcc855a
commit 69d169f5f6
2 changed files with 16 additions and 4 deletions

View File

@ -90,12 +90,17 @@ This permission is suitable if you want to your API to allow read permissions to
## DjangoModelPermissions ## DjangoModelPermissions
This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. When applied to a view that has a `.model` property, authorization will only be granted if the user has the relevant model permissions assigned. This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. When applied to a view that has a `.model` property, authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned.
* `POST` requests require the user to have the `add` permission on the model. * `POST` requests require the user to have the `add` permission on the model.
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model. * `PUT` and `PATCH` requests require the user to have the `change` permission on the model.
* `DELETE` requests require the user to have the `delete` permission on the model. * `DELETE` requests require the user to have the `delete` permission on the model.
If you want to use `DjangoModelPermissions` but also allow unauthenticated users to have read permission, override the class and set the `authenticated_users_only` property to `False`. For example:
class HasModelPermissionsOrReadOnly(DjangoModelPermissions):
authenticated_users_only = False
The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests. The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests.
To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details.

View File

@ -102,6 +102,8 @@ class DjangoModelPermissions(BasePermission):
'DELETE': ['%(app_label)s.delete_%(model_name)s'], 'DELETE': ['%(app_label)s.delete_%(model_name)s'],
} }
authenticated_users_only = True
def get_required_permissions(self, method, model_cls): def get_required_permissions(self, method, model_cls):
""" """
Given a model and an HTTP method, return the list of permission Given a model and an HTTP method, return the list of permission
@ -115,13 +117,18 @@ class DjangoModelPermissions(BasePermission):
def has_permission(self, request, view): def has_permission(self, request, view):
model_cls = getattr(view, 'model', None) model_cls = getattr(view, 'model', None)
if not model_cls: queryset = getattr(view, 'queryset', None)
return True
if model_cls is None and queryset is not None:
model_cls = queryset.model
assert model_cls, ('Cannot apply DjangoModelPermissions on a view that'
' does not have `.model` or `.queryset` property.')
perms = self.get_required_permissions(request.method, model_cls) perms = self.get_required_permissions(request.method, model_cls)
if (request.user and if (request.user and
request.user.is_authenticated() and (request.user.is_authenticated() or not self.authenticated_users_only) and
request.user.has_perms(perms)): request.user.has_perms(perms)):
return True return True
return False return False