Django permission error

I currently have a simple model defined, with a photoupload feature using django thumbnails plugin. but when i try to upload it gives me the following error: OSError at /admin/products/photo/add...

I currently have a simple model defined, with a photoupload feature using django thumbnails plugin.

but when i try to upload it gives me the following error:

OSError at /admin/products/photo/add/

(13, 'Permission denied')

Now, i know this is seems to be a permission issue, so the first thing i checked were permissions on the directory and changed these to 777 (Just to Test), restarted the server and fcgi and it still gives the error.

Traceback

Traceback: File "/usr/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response
  92.                 response = callback(request, *callback_args,
**callback_kwargs) File "/usr/lib/python2.6/dist-packages/django/contrib/admin/options.py" in wrapper
  226.                 return self.admin_site.admin_view(view)(*args,
**kwargs) File "/usr/lib/python2.6/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs) File "/usr/lib/python2.6/dist-packages/django/contrib/admin/sites.py" in inner
  186.             return view(request, *args, **kwargs) File "/usr/lib/python2.6/dist-packages/django/db/transaction.py" in _commit_on_success
  240.                 res = func(*args, **kw) File "/usr/lib/python2.6/dist-packages/django/contrib/admin/options.py" in add_view
  734.                 self.save_model(request, new_object, form, change=False) File "/usr/lib/python2.6/dist-packages/django/contrib/admin/options.py" in save_model
  557.         obj.save() File "/usr/lib/python2.6/dist-packages/django/db/models/base.py" in save
  410.         self.save_base(force_insert=force_insert, force_update=force_update) File "/usr/lib/python2.6/dist-packages/django/db/models/base.py" in save_base
  483.                     values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)] File "/usr/lib/python2.6/dist-packages/django/db/models/fields/files.py" in pre_save
  252.             file.save(file.name, file, save=False) File "/var/www/django_projects/gang/../gang/products/thumbs.py" in save
  84.         super(ImageWithThumbsFieldFile, self).save(name, content, save) File "/usr/lib/python2.6/dist-packages/django/db/models/fields/files.py" in save
  91.         self.name = self.storage.save(name, content) File "/usr/lib/python2.6/dist-packages/django/core/files/storage.py" in save
  47.         name = self._save(name, content) File "/usr/lib/python2.6/dist-packages/django/core/files/storage.py" in _save
  146.             os.makedirs(directory) File "/usr/lib/python2.6/os.py" in makedirs
  150.             makedirs(head, mode) File "/usr/lib/python2.6/os.py" in makedirs
  150.             makedirs(head, mode) File "/usr/lib/python2.6/os.py" in makedirs
  150.             makedirs(head, mode) File "/usr/lib/python2.6/os.py" in makedirs
  157.     mkdir(name, mode)

Exception Type: OSError at /admin/products/photo/add/ Exception Value: (13, 'Permission denied')

The user that the FCGI daemon is being run on definitely has access to read and write to that directory.

From settings.py

MEDIA_ROOT = '/var/www/sites/gang/http/media/'
MEDIA_ROOT_URL = '/media/'

  • Getting Help

  • el

  • es

  • fr

  • id

  • it

  • ja

  • ko

  • pl

  • pt-br

  • zh-hans

  • Language: en
  • 1.8

  • 1.10

  • 1.11

  • 2.0

  • 2.1

  • 2.2

  • 3.0

  • 3.1

  • 3.2

  • 4.0

  • 4.2

  • dev

  • Documentation version:
    4.1

Built-in Views¶

Several of Django’s built-in views are documented in
Writing views as well as elsewhere in the documentation.

Serving files in development¶

static.serve(request, path, document_root, show_indexes=False

There may be files other than your project’s static assets that, for
convenience, you’d like to have Django serve for you in local development.
The serve() view can be used to serve any directory
you give it. (This view is not hardened for production use and should be
used only as a development aid; you should serve these files in production
using a real front-end web server).

The most likely example is user-uploaded content in MEDIA_ROOT.
django.contrib.staticfiles is intended for static assets and has no
built-in handling for user-uploaded files, but you can have Django serve your
MEDIA_ROOT by appending something like this to your URLconf:

from django.conf import settings
from django.urls import re_path
from django.views.static import serve

# ... the rest of your URLconf goes here ...

if settings.DEBUG:
    urlpatterns += [
        re_path(r'^media/(?P<path>.*)$', serve, {
            'document_root': settings.MEDIA_ROOT,
        }),
    ]

Note, the snippet assumes your MEDIA_URL has a value of
'media/'. This will call the serve() view,
passing in the path from the URLconf and the (required) document_root
parameter.

Since it can become a bit cumbersome to define this URL pattern, Django
ships with a small URL helper function static()
that takes as parameters the prefix such as MEDIA_URL and a dotted
path to a view, such as 'django.views.static.serve'. Any other function
parameter will be transparently passed to the view.

Error views¶

Django comes with a few views by default for handling HTTP errors. To override
these with your own custom views, see Customizing error views.

The 404 (page not found) view¶

defaults.page_not_found(request, exception, template_name=‘404.html’

When you raise Http404 from within a view, Django loads a
special view devoted to handling 404 errors. By default, it’s the view
django.views.defaults.page_not_found(), which either produces a “Not
Found” message or loads and renders the template 404.html if you created it
in your root template directory.

The default 404 view will pass two variables to the template: request_path,
which is the URL that resulted in the error, and exception, which is a
useful representation of the exception that triggered the view (e.g. containing
any message passed to a specific Http404 instance).

Three things to note about 404 views:

  • The 404 view is also called if Django doesn’t find a match after
    checking every regular expression in the URLconf.
  • The 404 view is passed a RequestContext and
    will have access to variables supplied by your template context
    processors (e.g. MEDIA_URL).
  • If DEBUG is set to True (in your settings module), then
    your 404 view will never be used, and your URLconf will be displayed
    instead, with some debug information.

The 500 (server error) view¶

defaults.server_error(request, template_name=‘500.html’

Similarly, Django executes special-case behavior in the case of runtime errors
in view code. If a view results in an exception, Django will, by default, call
the view django.views.defaults.server_error, which either produces a
“Server Error” message or loads and renders the template 500.html if you
created it in your root template directory.

The default 500 view passes no variables to the 500.html template and is
rendered with an empty Context to lessen the chance of additional errors.

If DEBUG is set to True (in your settings module), then
your 500 view will never be used, and the traceback will be displayed
instead, with some debug information.

The 403 (HTTP Forbidden) view¶

defaults.permission_denied(request, exception, template_name=‘403.html’

In the same vein as the 404 and 500 views, Django has a view to handle 403
Forbidden errors. If a view results in a 403 exception then Django will, by
default, call the view django.views.defaults.permission_denied.

This view loads and renders the template 403.html in your root template
directory, or if this file does not exist, instead serves the text
“403 Forbidden”, as per RFC 7231#section-6.5.3 (the HTTP 1.1 Specification).
The template context contains exception, which is the string
representation of the exception that triggered the view.

django.views.defaults.permission_denied is triggered by a
PermissionDenied exception. To deny access in a
view you can use code like this:

from django.core.exceptions import PermissionDenied

def edit(request, pk):
    if not request.user.is_staff:
        raise PermissionDenied
    # ...

The 400 (bad request) view¶

defaults.bad_request(request, exception, template_name=‘400.html’

When a SuspiciousOperation is raised in Django,
it may be handled by a component of Django (for example resetting the session
data). If not specifically handled, Django will consider the current request a
‘bad request’ instead of a server error.

django.views.defaults.bad_request, is otherwise very similar to the
server_error view, but returns with the status code 400 indicating that
the error condition was the result of a client operation. By default, nothing
related to the exception that triggered the view is passed to the template
context, as the exception message might contain sensitive information like
filesystem paths.

bad_request views are also only used when DEBUG is False.

Back to Top

Содержание

  1. Documentation
  2. Built-in Views¶
  3. Serving files in development¶
  4. Error views¶
  5. The 404 (page not found) view¶
  6. The 500 (server error) view¶
  7. The 403 (HTTP Forbidden) view¶
  8. The 400 (bad request) view¶
  9. Exceptions
  10. Exception handling in REST framework views
  11. Custom exception handling
  12. API Reference
  13. APIException
  14. Inspecting API exceptions
  15. ParseError
  16. AuthenticationFailed
  17. NotAuthenticated
  18. PermissionDenied
  19. NotFound
  20. MethodNotAllowed
  21. NotAcceptable
  22. UnsupportedMediaType
  23. Throttled
  24. ValidationError
  25. Generic Error Views
  26. rest_framework.exceptions.server_error
  27. rest_framework.exceptions.bad_request
  28. Third party packages
  29. DRF Standardized Errors
  30. django.core.exceptions PermissionDenied Example Code
  31. Example 1 from django-allauth
  32. Example 2 from django-axes
  33. Example 3 from django-cms
  34. Example 4 from django-downloadview
  35. Example 5 from django-filer
  36. Example 6 from django-guardian
  37. Example 7 from django-haystack
  38. Example 8 from django-import-export
  39. Example 9 from django-loginas
  40. Example 10 from django-rest-framework
  41. Example 11 from wagtail

Documentation

Built-in Views¶

Several of Django’s built-in views are documented in Writing views as well as elsewhere in the documentation.

Serving files in development¶

There may be files other than your project’s static assets that, for convenience, you’d like to have Django serve for you in local development. The serve() view can be used to serve any directory you give it. (This view is not hardened for production use and should be used only as a development aid; you should serve these files in production using a real front-end web server).

The most likely example is user-uploaded content in MEDIA_ROOT . django.contrib.staticfiles is intended for static assets and has no built-in handling for user-uploaded files, but you can have Django serve your MEDIA_ROOT by appending something like this to your URLconf:

Note, the snippet assumes your MEDIA_URL has a value of ‘media/’ . This will call the serve() view, passing in the path from the URLconf and the (required) document_root parameter.

Since it can become a bit cumbersome to define this URL pattern, Django ships with a small URL helper function static() that takes as parameters the prefix such as MEDIA_URL and a dotted path to a view, such as ‘django.views.static.serve’ . Any other function parameter will be transparently passed to the view.

Error views¶

Django comes with a few views by default for handling HTTP errors. To override these with your own custom views, see Customizing error views .

The 404 (page not found) view¶

When you raise Http404 from within a view, Django loads a special view devoted to handling 404 errors. By default, it’s the view django.views.defaults.page_not_found() , which either produces a “Not Found” message or loads and renders the template 404.html if you created it in your root template directory.

The default 404 view will pass two variables to the template: request_path , which is the URL that resulted in the error, and exception , which is a useful representation of the exception that triggered the view (e.g. containing any message passed to a specific Http404 instance).

Three things to note about 404 views:

  • The 404 view is also called if Django doesn’t find a match after checking every regular expression in the URLconf.
  • The 404 view is passed a RequestContext and will have access to variables supplied by your template context processors (e.g. MEDIA_URL ).
  • If DEBUG is set to True (in your settings module), then your 404 view will never be used, and your URLconf will be displayed instead, with some debug information.

The 500 (server error) view¶

Similarly, Django executes special-case behavior in the case of runtime errors in view code. If a view results in an exception, Django will, by default, call the view django.views.defaults.server_error , which either produces a “Server Error” message or loads and renders the template 500.html if you created it in your root template directory.

The default 500 view passes no variables to the 500.html template and is rendered with an empty Context to lessen the chance of additional errors.

If DEBUG is set to True (in your settings module), then your 500 view will never be used, and the traceback will be displayed instead, with some debug information.

The 403 (HTTP Forbidden) view¶

In the same vein as the 404 and 500 views, Django has a view to handle 403 Forbidden errors. If a view results in a 403 exception then Django will, by default, call the view django.views.defaults.permission_denied .

This view loads and renders the template 403.html in your root template directory, or if this file does not exist, instead serves the text “403 Forbidden”, as per RFC 7231#section-6.5.3 (the HTTP 1.1 Specification). The template context contains exception , which is the string representation of the exception that triggered the view.

django.views.defaults.permission_denied is triggered by a PermissionDenied exception. To deny access in a view you can use code like this:

The 400 (bad request) view¶

When a SuspiciousOperation is raised in Django, it may be handled by a component of Django (for example resetting the session data). If not specifically handled, Django will consider the current request a ‘bad request’ instead of a server error.

django.views.defaults.bad_request , is otherwise very similar to the server_error view, but returns with the status code 400 indicating that the error condition was the result of a client operation. By default, nothing related to the exception that triggered the view is passed to the template context, as the exception message might contain sensitive information like filesystem paths.

bad_request views are also only used when DEBUG is False .

Источник

Exceptions

Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.

Exception handling in REST framework views

REST framework’s views handle various exceptions, and deal with returning appropriate error responses.

The handled exceptions are:

  • Subclasses of APIException raised inside REST framework.
  • Django’s Http404 exception.
  • Django’s PermissionDenied exception.

In each case, REST framework will return a response with an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error.

Most error responses will include a key detail in the body of the response.

For example, the following request:

Might receive an error response indicating that the DELETE method is not allowed on that resource:

Validation errors are handled slightly differently, and will include the field names as the keys in the response. If the validation error was not specific to a particular field then it will use the «non_field_errors» key, or whatever string value has been set for the NON_FIELD_ERRORS_KEY setting.

An example validation error might look like this:

Custom exception handling

You can implement custom exception handling by creating a handler function that converts exceptions raised in your API views into response objects. This allows you to control the style of error responses used by your API.

The function must take a pair of arguments, the first is the exception to be handled, and the second is a dictionary containing any extra context such as the view currently being handled. The exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 ‘server error’ response.

For example, you might want to ensure that all error responses include the HTTP status code in the body of the response, like so:

In order to alter the style of the response, you could write the following custom exception handler:

The context argument is not used by the default handler, but can be useful if the exception handler needs further information such as the view currently being handled, which can be accessed as context[‘view’] .

The exception handler must also be configured in your settings, using the EXCEPTION_HANDLER setting key. For example:

If not specified, the ‘EXCEPTION_HANDLER’ setting defaults to the standard exception handler provided by REST framework:

Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

API Reference

APIException

Signature: APIException()

The base class for all exceptions raised inside an APIView class or @api_view .

To provide a custom exception, subclass APIException and set the .status_code , .default_detail , and default_code attributes on the class.

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:

Inspecting API exceptions

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.

The available attributes and methods are:

  • .detail — Return the textual description of the error.
  • .get_codes() — Return the code identifier of the error.
  • .get_full_details() — Return both the textual description and the code identifier.

In most cases the error detail will be a simple item:

In the case of validation errors the error detail will be either a list or dictionary of items:

ParseError

Signature: ParseError(detail=None, code=None)

Raised if the request contains malformed data when accessing request.data .

By default this exception results in a response with the HTTP status code «400 Bad Request».

AuthenticationFailed

Signature: AuthenticationFailed(detail=None, code=None)

Raised when an incoming request includes incorrect authentication.

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 authentication documentation for more details.

NotAuthenticated

Signature: NotAuthenticated(detail=None, code=None)

Raised when an unauthenticated request fails the permission checks.

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 authentication documentation for more details.

PermissionDenied

Signature: PermissionDenied(detail=None, code=None)

Raised when an authenticated request fails the permission checks.

By default this exception results in a response with the HTTP status code «403 Forbidden».

NotFound

Signature: NotFound(detail=None, code=None)

Raised when a resource does not exists at the given URL. This exception is equivalent to the standard Http404 Django exception.

By default this exception results in a response with the HTTP status code «404 Not Found».

MethodNotAllowed

Signature: MethodNotAllowed(method, detail=None, code=None)

Raised when an incoming request occurs that does not map to a handler method on the view.

By default this exception results in a response with the HTTP status code «405 Method Not Allowed».

NotAcceptable

Signature: NotAcceptable(detail=None, code=None)

Raised when an incoming request occurs with an Accept header that cannot be satisfied by any of the available renderers.

By default this exception results in a response with the HTTP status code «406 Not Acceptable».

Signature: UnsupportedMediaType(media_type, detail=None, code=None)

Raised if there are no parsers that can handle the content type of the request data when accessing request.data .

By default this exception results in a response with the HTTP status code «415 Unsupported Media Type».

Throttled

Signature: Throttled(wait=None, detail=None, code=None)

Raised when an incoming request fails the throttling checks.

By default this exception results in a response with the HTTP status code «429 Too Many Requests».

ValidationError

Signature: ValidationError(detail, code=None)

The ValidationError exception is slightly different from the other APIException classes:

  • The detail argument is mandatory, not optional.
  • The detail argument may be a list or dictionary of error details, and may also be a nested data structure. By using a dictionary, you can specify field-level errors while performing object-level validation in the validate() method of a serializer. For example. raise serializers.ValidationError(<‘name’: ‘Please enter a valid name.’>)
  • By convention you should import the serializers module and use a fully qualified ValidationError style, in order to differentiate it from Django’s built-in validation error. For example. raise serializers.ValidationError(‘This field must be an integer value.’)

The ValidationError class should be used for serializer and field validation, and by validator classes. It is also raised when calling serializer.is_valid with the raise_exception keyword argument:

The generic views use the raise_exception=True flag, which means that you can override the style of validation error responses globally in your API. To do so, use a custom exception handler, as described above.

By default this exception results in a response with the HTTP status code «400 Bad Request».

Generic Error Views

Django REST Framework provides two error views suitable for providing generic JSON 500 Server Error and 400 Bad Request responses. (Django’s default error views provide HTML responses, which may not be appropriate for an API-only application.)

rest_framework.exceptions.server_error

Returns a response with status code 500 and application/json content type.

Set as handler500 :

rest_framework.exceptions.bad_request

Returns a response with status code 400 and application/json content type.

Set as handler400 :

Third party packages

The following third-party packages are also available.

DRF Standardized Errors

The drf-standardized-errors package provides an exception handler that generates the same format for all 4xx and 5xx responses. It is a drop-in replacement for the default exception handler and allows customizing the error response format without rewriting the whole exception handler. The standardized error response format is easier to document and easier to handle by API consumers.

Источник

django.core.exceptions PermissionDenied Example Code

PermissionDenied is a class within the django.core.exceptions module of the Django project.

Example 1 from django-allauth

django-allauth (project website) is a Django library for easily adding local and social authentication flows to Django projects. It is open source under the MIT License.

Example 2 from django-axes

django-axes (project documentation and PyPI package information is a code library for Django projects to track failed login attempts against a web application. The goal of the project is to make it easier for you to stop people and scripts from hacking your Django-powered website.

The code for django-axes is open source under the MIT license and maintained by the group of developers known as Jazzband.

Example 3 from django-cms

django-cms (project website) is a Python-based content management system (CMS) library for use with Django web apps that is open sourced under the BSD 3-Clause «New» license.

Example 4 from django-downloadview

django-downloadview (project documentation and PyPI package information) is a Django extension for serving downloads through your web application. While typically you would use a web server to handle static content, sometimes you need to control file access, such as requiring a user to register before downloading a PDF. In that situations, django-downloadview is a handy library to avoid boilerplate code for common scenarios.

Example 5 from django-filer

django-filer (project documentation) is a file management library for uploading and organizing files and images in Django’s admin interface. The project’s code is available under the BSD 3-Clause «New» or «Revised» open source license.

Example 6 from django-guardian

django-guardian (project documentation and PyPI page) provides per-object permissions in Django projects by enhancing the existing authentication backend. The project’s code is open source under the MIT license.

Example 7 from django-haystack

django-haystack (project website and PyPI page) is a search abstraction layer that separates the Python search code in a Django web application from the search engine implementation that it runs on, such as Apache Solr, Elasticsearch or Whoosh.

The django-haystack project is open source under the BSD license.

Example 8 from django-import-export

django-import-export (documentation and PyPI page) is a Django code library for importing and exporting data from the Django Admin. The tool supports many export and import formats such as CSV, JSON and YAML. django-import-export is open source under the BSD 2-Clause «Simplified» License.

Example 9 from django-loginas

django-loginas (PyPI package information) is Django code library for admins to log into an application as another user, typically for debugging purposes.

django-loginas is open source under the BSD 3-Clause «New» or «Revised» License.

Example 10 from django-rest-framework

Django REST Framework (project homepage and documentation, PyPI package information and more resources on Full Stack Python), often abbreviated as «DRF», is a popular Django extension for building web APIs. The project has fantastic documentation and a wonderful quickstart that serve as examples of how to make it easier for newcomers to get started.

The project is open sourced under the Encode OSS Ltd. license.

Example 11 from wagtail

wagtail (project website) is a fantastic Django-based CMS with code that is open source under the BSD 3-Clause «New» or «Revised» License.

Источник

permissions.py

Authentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.

— Apple Developer Documentation

Together with authentication and throttling, permissions determine whether a request should be granted or denied access.

Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the request.user and request.auth properties to determine if the incoming request should be permitted.

Permissions are used to grant or deny access for different classes of users to different parts of the API.

The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds to the IsAuthenticated class in REST framework.

A slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the IsAuthenticatedOrReadOnly class in REST framework.

How permissions are determined

Permissions in REST framework are always defined as a list of permission classes.

Before running the main body of the view each permission in the list is checked.
If any permission check fails, an exceptions.PermissionDenied or exceptions.NotAuthenticated exception will be raised, and the main body of the view will not run.

When the permission checks fail, either a «403 Forbidden» or a «401 Unauthorized» response will be returned, according to the following rules:

  • The request was successfully authenticated, but permission was denied. — An HTTP 403 Forbidden response will be returned.
  • The request was not successfully authenticated, and the highest priority authentication class does not use WWW-Authenticate headers. — An HTTP 403 Forbidden response will be returned.
  • The request was not successfully authenticated, and the highest priority authentication class does use WWW-Authenticate headers. — An HTTP 401 Unauthorized response, with an appropriate WWW-Authenticate header will be returned.

Object level permissions

REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.

Object level permissions are run by REST framework’s generic views when .get_object() is called.
As with view level permissions, an exceptions.PermissionDenied exception will be raised if the user is not allowed to act on the given object.

If you’re writing your own views and want to enforce object level permissions,
or if you override the get_object method on a generic view, then you’ll need to explicitly call the .check_object_permissions(request, obj) method on the view at the point at which you’ve retrieved the object.

This will either raise a PermissionDenied or NotAuthenticated exception, or simply return if the view has the appropriate permissions.

For example:

def get_object(self):
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
    self.check_object_permissions(self.request, obj)
    return obj

Note: With the exception of DjangoObjectPermissions, the provided
permission classes in rest_framework.permissions do not implement the
methods necessary to check object permissions.

If you wish to use the provided permission classes in order to check object
permissions, you must subclass them and implement the
has_object_permission() method described in the Custom
permissions
section (below).


Limitations of object level permissions

For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.

Often when you’re using object level permissions you’ll also want to filter the queryset appropriately, to ensure that users only have visibility onto instances that they are permitted to view.

Because the get_object() method is not called, object level permissions from the has_object_permission() method are not applied when creating objects. In order to restrict object creation you need to implement the permission check either in your Serializer class or override the perform_create() method of your ViewSet class.

Setting the permission policy

The default permission policy may be set globally, using the DEFAULT_PERMISSION_CLASSES setting. For example.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

If not specified, this setting defaults to allowing unrestricted access:

'DEFAULT_PERMISSION_CLASSES': [
   'rest_framework.permissions.AllowAny',
]

You can also set the authentication policy on a per-view, or per-viewset basis,
using the APIView class-based views.

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Or, if you’re using the @api_view decorator with function based views.

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

Note: when you set new permission classes via the class attribute or decorators you’re telling the view to ignore the default list set in the settings.py file.

Provided they inherit from rest_framework.permissions.BasePermission, permissions can be composed using standard Python bitwise operators. For example, IsAuthenticatedOrReadOnly could be written:

from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = [IsAuthenticated|ReadOnly]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Note: it supports & (and), | (or) and ~ (not).


API Reference

AllowAny

The AllowAny permission class will allow unrestricted access, regardless of if the request was authenticated or unauthenticated.

This permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.

IsAuthenticated

The IsAuthenticated permission class will deny permission to any unauthenticated user, and allow permission otherwise.

This permission is suitable if you want your API to only be accessible to registered users.

IsAdminUser

The IsAdminUser permission class will deny permission to any user, unless user.is_staff is True in which case permission will be allowed.

This permission is suitable if you want your API to only be accessible to a subset of trusted administrators.

IsAuthenticatedOrReadOnly

The IsAuthenticatedOrReadOnly will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the «safe» methods; GET, HEAD or OPTIONS.

This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.

DjangoModelPermissions

This permission class ties into Django’s standard django.contrib.auth model permissions. 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 model permissions assigned. The appropriate model is determined by checking get_queryset().model or queryset.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.
  • DELETE requests require the user to have the delete permission on the model.

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.

DjangoModelPermissionsOrAnonReadOnly

Similar to DjangoModelPermissions, but also allows unauthenticated users to have read-only access to the API.

DjangoObjectPermissions

This permission class ties into Django’s standard object permissions framework 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.

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.
  • DELETE requests require the user to have the delete permission on the model instance.

Note that DjangoObjectPermissions does not require the django-guardian package, and should support other object-level backends equally well.

As with DjangoModelPermissions you can use custom model permissions by overriding DjangoObjectPermissions and setting the .perms_map property. Refer to the source code for details.


Note: If you need object level view permissions for GET, HEAD and OPTIONS requests and are using django-guardian for your object-level permissions backend, you’ll want to consider using the DjangoObjectPermissionsFilter class provided by the djangorestframework-guardian package. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.


Custom permissions

To implement a custom permission, override BasePermission and implement either, or both, of the following methods:

  • .has_permission(self, request, view)
  • .has_object_permission(self, request, view, obj)

The methods should return True if the request should be granted access, and False otherwise.

If you need to test if a request is a read operation or a write operation, you should check the request method against the constant SAFE_METHODS, which is a tuple containing 'GET', 'OPTIONS' and 'HEAD'. For example:

if request.method in permissions.SAFE_METHODS:
    # Check permissions for read-only request
else:
    # Check permissions for write request

Note: The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call .check_object_permissions(request, obj). If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising PermissionDenied on failure.)


Custom permissions will raise a PermissionDenied exception if the test fails. To change the error message associated with the exception, implement a message attribute directly on your custom permission. Otherwise the default_detail attribute from PermissionDenied will be used. Similarly, to change the code identifier associated with the exception, implement a code attribute directly on your custom permission — otherwise the default_code attribute from PermissionDenied will be used.

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view):
         ...

Examples

The following is an example of a permission class that checks the incoming request’s IP address against a blocklist, and denies the request if the IP has been blocked.

from rest_framework import permissions

class BlocklistPermission(permissions.BasePermission):
    """
    Global permission check for blocked IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blocked = Blocklist.objects.filter(ip_addr=ip_addr).exists()
        return not blocked

As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Instance must have an attribute named `owner`.
        return obj.owner == request.user

Note that the generic views will check the appropriate object level permissions, but if you’re writing your own custom views, you’ll need to make sure you check the object level permission checks yourself. You can do so by calling self.check_object_permissions(request, obj) from the view once you have the object instance. This call will raise an appropriate APIException if any object-level permission checks fail, and will otherwise simply return.

Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you’ll need to filter the queryset separately. See the filtering documentation for more details.

Overview of access restriction methods

REST framework offers three different methods to customize access restrictions on a case-by-case basis. These apply in different scenarios and have different effects and limitations.

  • queryset/get_queryset(): Limits the general visibility of existing objects from the database. The queryset limits which objects will be listed and which objects can be modified or deleted. The get_queryset() method can apply different querysets based on the current action.
  • permission_classes/get_permissions(): General permission checks based on the current action, request and targeted object. Object level permissions can only be applied to retrieve, modify and deletion actions. Permission checks for list and create will be applied to the entire object type. (In case of list: subject to restrictions in the queryset.)
  • serializer_class/get_serializer(): Instance level restrictions that apply to all objects on input and output. The serializer may have access to the request context. The get_serializer() method can apply different serializers based on the current action.

The following table lists the access restriction methods and the level of control they offer over which actions.

queryset permission_classes serializer_class
Action: list global global object-level*
Action: create no global object-level
Action: retrieve global object-level object-level
Action: update global object-level object-level
Action: partial_update global object-level object-level
Action: destroy global object-level no
Can reference action in decision no** yes no**
Can reference request in decision no** yes yes

* A Serializer class should not raise PermissionDenied in a list action, or the entire list would not be returned.
** The get_*() methods have access to the current view and can return different Serializer or QuerySet instances based on the request or action.


Third party packages

The following third party packages are also available.

DRF — Access Policy

The Django REST — Access Policy package provides a way to define complex access rules in declarative policy classes that are attached to view sets or function-based views. The policies are defined in JSON in a format similar to AWS’ Identity & Access Management policies.

Composed Permissions

The Composed Permissions package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.

REST Condition

The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.

DRY Rest Permissions

The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app’s data model. It also supports permission checks being returned to a client app through the API’s serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.

Django Rest Framework Roles

The Django Rest Framework Roles package makes it easier to parameterize your API over multiple types of users.

Django REST Framework API Key

The Django REST Framework API Key package provides permissions classes, models and helpers to add API key authorization to your API. It can be used to authorize internal or third-party backends and services (i.e. machines) which do not have a user account. API keys are stored securely using Django’s password hashing infrastructure, and they can be viewed, edited and revoked at anytime in the Django admin.

Django Rest Framework Role Filters

The Django Rest Framework Role Filters package provides simple filtering over multiple types of roles.

Django Rest Framework PSQ

The Django Rest Framework PSQ package is an extension that gives support for having action-based permission_classes, serializer_class, and queryset dependent on permission-based rules.

Разрешения¶

Аутентификация или идентификация сами по себе обычно недостаточны для получения доступа к информации или коду. Для этого субъект, запрашивающий доступ, должен иметь авторизацию.

Apple Developer Documentation

Вместе с authentication и :doc:`throttling <throttling>`** , разрешения определяют, должен ли запрос быть удовлетворен или в доступе должно быть отказано.

Проверка разрешений всегда выполняется в самом начале представления, до того, как будет разрешено выполнение любого другого кода. Проверка разрешений обычно использует информацию об аутентификации в свойствах request.user и request.auth, чтобы определить, должен ли быть разрешен входящий запрос.

Разрешения используются для предоставления или запрета доступа различных классов пользователей к различным частям API.

Самый простой стиль разрешения — разрешить доступ любому аутентифицированному пользователю и запретить доступ любому неаутентифицированному пользователю. Это соответствует классу IsAuthenticated в REST framework.

Чуть менее строгий стиль разрешения — разрешить полный доступ для аутентифицированных пользователей, но разрешить доступ только для чтения для неаутентифицированных пользователей. Это соответствует классу IsAuthenticatedOrReadOnly в REST framework.

Как определяются разрешения¶

Разрешения в REST-фреймворке всегда определяются как список классов разрешений.

Перед запуском основной части представления проверяется каждое разрешение в списке. Если проверка какого-либо разрешения не прошла, будет вызвано исключение exceptions.PermissionDenied или exceptions.NotAuthenticated, и основное тело представления не будет запущено.

При неудачной проверке разрешений возвращается либо ответ «403 Forbidden», либо ответ «401 Unauthorized», в соответствии со следующими правилами:

  • Запрос был успешно аутентифицирован, но в разрешении было отказано. — Будет возвращен ответ HTTP 403 Forbidden.

  • Запрос не был успешно аутентифицирован, а класс аутентификации с наивысшим приоритетом не использует заголовки WWW-Authenticate. — Будет возвращен ответ HTTP 403 Forbidden.

  • Запрос не был успешно аутентифицирован, а класс аутентификации с наивысшим приоритетом должен использовать заголовки WWW-Authenticate. — Будет возвращен ответ HTTP 401 Unauthorized с соответствующим заголовком «WWW-Authenticate«.

Разрешения на уровне объекта¶

Разрешения фреймворка REST также поддерживают разрешения на уровне объектов. Разрешения на уровне объекта используются для определения того, разрешено ли пользователю действовать с определенным объектом, который обычно является экземпляром модели.

Разрешения на уровне объектов выполняются общими представлениями REST framework при вызове .get_object(). Как и в случае с разрешениями на уровне представления, исключение exceptions.PermissionDenied будет вызвано, если пользователю не разрешено действовать с данным объектом.

Если вы пишете собственные представления и хотите обеспечить разрешения на уровне объектов, или если вы переопределите метод get_object в общем представлении, то вам нужно будет явно вызвать метод .check_object_permissions(request, obj) в представлении в тот момент, когда вы извлекли объект.

Это либо вызовет исключение PermissionDenied или NotAuthenticated, либо просто вернется, если представление имеет соответствующие разрешения.

Например:

def get_object(self):
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
    self.check_object_permissions(self.request, obj)
    return obj

Примечание : За исключением DjangoObjectPermissions , предоставленные классы разрешений в rest_framework.permissions не реализуют методы, необходимые для проверки разрешений объектов.

Если вы хотите использовать предоставленные классы разрешений для проверки разрешений объектов, вы должны подклассифицировать их и реализовать метод has_object_permission(), описанный в разделе ** *Custom permissions* (ниже).


Ограничения разрешений на уровне объекта¶

По причинам производительности общие представления не будут автоматически применять разрешения на уровне объекта к каждому экземпляру в наборе запросов при возврате списка объектов.

Часто, когда вы используете разрешения на уровне объекта, вы также хотите filter the queryset соответствующим образом, чтобы гарантировать, что пользователи имеют видимость только тех экземпляров, которые им разрешено просматривать.

Поскольку метод get_object() не вызывается, разрешения объектного уровня из метода has_object_permission() не применяются при создании объектов. Чтобы ограничить создание объектов, вам необходимо реализовать проверку прав либо в классе Serializer, либо переопределить метод perform_create()> вашего класса ViewSet.

Настройка политики разрешений¶

Политика разрешений по умолчанию может быть установлена глобально, с помощью параметра DEFAULT_PERMISSION_CLASSES. Например.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

Если этот параметр не указан, то по умолчанию он разрешает неограниченный доступ:

'DEFAULT_PERMISSION_CLASSES': [
   'rest_framework.permissions.AllowAny',
]

Вы также можете установить политику аутентификации на основе каждого представления или каждого набора представлений, используя APIView представления на основе класса.

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Или, если вы используете декоратор @api_view с представлениями, основанными на функциях.

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

Примечание: когда вы устанавливаете новые классы разрешений с помощью атрибута class или декораторов, вы говорите представлению игнорировать список по умолчанию, установленный в файле settings.py.

Если они наследуются от rest_framework.permissions.BasePermission , разрешения могут быть составлены с помощью стандартных побитовых операторов Python. Например, IsAuthenticatedOrReadOnly можно записать:

from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = [IsAuthenticated|ReadOnly]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Примечание: он поддерживает & (и), | (или) и ~ (не).


Справочник по API¶

AllowAny¶

Класс разрешения AllowAny разрешает неограниченный доступ, независимо от того, был ли запрос аутентифицирован или неаутентифицирован.

Это разрешение не является строго обязательным, поскольку вы можете достичь того же результата, используя пустой список или кортеж для установки разрешений, но вы можете посчитать полезным указать этот класс, поскольку он делает намерение явным.

IsAuthenticated¶

Класс разрешения IsAuthenticated будет запрещать разрешение любому неаутентифицированному пользователю, и разрешать в противном случае.

Это разрешение подходит, если вы хотите, чтобы ваш API был доступен только зарегистрированным пользователям.

IsAdminUser¶

Класс разрешения IsAdminUser будет запрещать разрешение любому пользователю, если только user.is_staff не является True, в этом случае разрешение будет разрешено.

Это разрешение подходит, если вы хотите, чтобы ваш API был доступен только подгруппе доверенных администраторов.

IsAuthenticatedOrReadOnly¶

IsAuthenticatedOrReadOnly позволит аутентифицированным пользователям выполнить любой запрос. Запросы неавторизованных пользователей будут разрешены, только если метод запроса является одним из «безопасных» методов; GET , HEAD или OPTIONS.

Это разрешение подходит, если вы хотите, чтобы ваш API разрешал права на чтение анонимным пользователям и разрешал права на запись только аутентифицированным пользователям.

DjangoModelPermissions¶

Этот класс разрешений связан со стандартом Django django.contrib.auth model permissions. Это разрешение должно применяться только к представлениям, имеющим .queryset свойство или get_queryset() метод. Разрешение будет предоставлено только в том случае, если пользователь аутентифицирован и имеет соответствующие разрешения модели.

  • Запросы POST требуют, чтобы пользователь имел разрешение add на модель.

  • Запросы PUT и PATCH требуют, чтобы пользователь имел разрешение change на модель.

  • Запросы DELETE требуют, чтобы пользователь имел разрешение delete на модель.

Поведение по умолчанию также можно переопределить для поддержки пользовательских разрешений модели. Например, вы можете включить разрешение модели view для запросов GET.

Чтобы использовать пользовательские разрешения модели, переопределите DjangoModelPermissions и установите свойство .perms_map. Подробности см. в исходном коде.

DjangoModelPermissionsOrAnonReadOnly¶

Аналогично DjangoModelPermissions , но также позволяет неаутентифицированным пользователям иметь доступ к API только для чтения.

 DjangoObjectPermissions¶

Этот класс разрешений связан со стандартом Django object permissions framework, который позволяет устанавливать разрешения на модели на уровне объекта. Чтобы использовать этот класс разрешений, вам также необходимо добавить бэкенд разрешений, который поддерживает разрешения на уровне объекта, такие как django-guardian.

Как и DjangoModelPermissions, это разрешение должно применяться только к представлениям, имеющим .queryset свойство или .get_queryset() метод. Разрешение будет предоставлено только в том случае, если пользователь аутентифицирован и имеет соответствующие разрешения на объект и соответствующие разрешения на модель.

  • Запросы POST требуют, чтобы пользователь имел разрешение add на экземпляр модели.

  • Запросы PUT и PATCH требуют, чтобы пользователь имел разрешение change на экземпляр модели.

  • Запросы DELETE требуют, чтобы пользователь имел разрешение delete на экземпляр модели.

Обратите внимание, что DjangoObjectPermissions **не требует пакета django-guardian, и должен одинаково хорошо поддерживать другие бэкенды объектного уровня.

Как и в случае с DjangoModelPermissions, вы можете использовать пользовательские разрешения модели, переопределив DjangoObjectPermissions и установив свойство .perms_map. Подробности см. в исходном коде.


Примечание : Если вам нужны разрешения на уровне объектов view для GET , HEAD и OPTIONS запросов и вы используете django-guardian для бэкенда разрешений на уровне объектов, вам стоит рассмотреть возможность использования класса DjangoObjectPermissionsFilter, предоставляемого ** «djangorestframework-guardian:doc:` package <https://github.com/rpkilby/django-rest-framework-guardian>`. Он гарантирует, что конечные точки списка возвращают только результаты, включающие объекты, для которых пользователь имеет соответствующие разрешения на просмотр.


Пользовательские разрешения¶

Чтобы реализовать пользовательское разрешение, переопределите BasePermission и реализуйте один или оба из следующих методов:

  • .has_permission(self, request, view)

  • .has_object_permission(self, request, view, obj)

Методы должны возвращать True, если запрос должен получить доступ, и False в противном случае.

Если вам нужно проверить, является ли запрос операцией чтения или записи, вы должны проверить метод запроса на соответствие константе SAFE_METHODS``** , которая является кортежем, содержащим ``'GET' , 'OPTIONS' и 'HEAD'. Например:

if request.method in permissions.SAFE_METHODS:
    # Check permissions for read-only request
else:
    # Check permissions for write request

Примечание : Метод has_object_permission уровня экземпляра будет вызван только в том случае, если проверки has_permission уровня представления уже прошли. Также обратите внимание, что для того, чтобы проверки на уровне экземпляра были выполнены, код представления должен явно вызвать .check_object_permissions(request, obj). Если вы используете общие представления, то это будет сделано за вас по умолчанию. (Представления, основанные на функциях, должны будут проверять разрешения объектов явно, вызывая PermissionDenied в случае неудачи).


Пользовательские разрешения будут вызывать исключение PermissionDenied, если тест не пройден. Чтобы изменить сообщение об ошибке, связанное с исключением, реализуйте атрибут message непосредственно на вашем пользовательском разрешении. В противном случае будет использован атрибут default_detail из PermissionDenied. Аналогично, чтобы изменить идентификатор кода, связанный с исключением, реализуйте атрибут code непосредственно на вашем пользовательском разрешении — иначе будет использоваться атрибут default_code из PermissionDenied.

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view):
         ...

Примеры¶

Ниже приведен пример класса разрешения, который проверяет IP-адрес входящего запроса по списку блокировки и отклоняет запрос, если IP-адрес был заблокирован.

from rest_framework import permissions

class BlocklistPermission(permissions.BasePermission):
    """
    Global permission check for blocked IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blocked = Blocklist.objects.filter(ip_addr=ip_addr).exists()
        return not blocked

Помимо глобальных разрешений, которые выполняются для всех входящих запросов, вы также можете создавать разрешения на уровне объекта, которые выполняются только для операций, затрагивающих конкретный экземпляр объекта. Например:

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Instance must have an attribute named `owner`.
        return obj.owner == request.user

Обратите внимание, что общие представления будут проверять соответствующие разрешения на уровне объекта, но если вы пишете свои собственные пользовательские представления, вам нужно будет убедиться, что вы сами проверяете разрешения на уровне объекта. Вы можете сделать это, вызвав self.check_object_permissions(request, obj) из представления, когда у вас есть экземпляр объекта. Этот вызов вызовет соответствующее сообщение APIException, если проверка разрешений на уровне объекта завершится неудачей, а в противном случае просто вернется.

Также обратите внимание, что общие представления будут проверять разрешения на уровне объекта только для представлений, которые получают один экземпляр модели. Если вам требуется фильтрация на уровне объектов для списковых представлений, вам придется фильтровать набор запросов отдельно. Более подробную информацию см. в filtering documentation.

Обзор методов ограничения доступа¶

Структура REST предлагает три различных метода настройки ограничений доступа в каждом конкретном случае. Они применяются в разных сценариях и имеют различные эффекты и ограничения.

  • queryset /** get_queryset() : Ограничивает общую видимость существующих объектов из базы данных. Кверисет ограничивает, какие объекты будут отображаться в списке и какие объекты могут быть изменены или удалены. Метод get_queryset()> может применять различные кверисеты в зависимости от текущего действия.

  • permission_classes /get_permissions(): Общая проверка прав доступа, основанная на текущем действии, запросе и целевом объекте. Разрешения на уровне объекта могут быть применены только к действиям получения, изменения и удаления. Проверки разрешений для list и create будут применены ко всему типу объекта. (В случае списка: с учетом ограничений в наборе запросов).

  • serializer_class /** get_serializer() : Ограничения на уровне экземпляра, которые применяются ко всем объектам на входе и выходе. Сериализатор может иметь доступ к контексту запроса. Метод get_serializer()> может применять различные сериализаторы в зависимости от текущего действия.

В следующей таблице перечислены методы ограничения доступа и уровень контроля, который они обеспечивают, над какими действиями.


Пакеты сторонних производителей¶

Также доступны следующие пакеты сторонних производителей.

DRF — Политика доступа¶

Пакет Django REST — Access Policy предоставляет способ определения сложных правил доступа в декларативных классах политик, которые прикрепляются к наборам представлений или представлениям на основе функций. Политики определяются в JSON в формате, аналогичном политикам AWS Identity & Access Management.

Составленные разрешения¶

Пакет Composed Permissions предоставляет простой способ определения сложных и многоглубинных (с логическими операторами) объектов разрешения, используя небольшие и многократно используемые компоненты.

Пакет REST Condition — это еще одно расширение для построения сложных разрешений простым и удобным способом. Расширение позволяет комбинировать разрешения с логическими операторами.

DRY Rest Permissions¶

Пакет DRY Rest Permissions предоставляет возможность определять различные разрешения для отдельных действий по умолчанию и пользовательских действий. Этот пакет предназначен для приложений с разрешениями, которые являются производными от отношений, определенных в модели данных приложения. Он также поддерживает проверку разрешений, возвращаемую клиентскому приложению через сериализатор API. Кроме того, он поддерживает добавление разрешений к действиям списка по умолчанию и пользовательским действиям списка для ограничения данных, которые они извлекают для каждого пользователя.

Роли Django Rest Framework¶

Пакет Django Rest Framework Roles облегчает параметризацию API для нескольких типов пользователей.

Django REST Framework API Key¶

Пакет Django REST Framework API Key предоставляет классы разрешений, модели и помощники для добавления авторизации по ключу API в ваш API. Он может быть использован для авторизации внутренних или сторонних бэкендов и сервисов (т.е. машин* ), которые не имеют учетной записи пользователя. API ключи хранятся в безопасном месте с использованием инфраструктуры хэширования паролей Django, и их можно просматривать, редактировать и отзывать в любое время в админке Django.

Ролевые фильтры Django Rest Framework¶

Пакет Django Rest Framework Role Filters обеспечивает простую фильтрацию по нескольким типам ролей.

Django Rest Framework PSQ¶

Пакет Django Rest Framework PSQ — это расширение, которое обеспечивает поддержку того, чтобы основанные на действиях классы_разрешений , сериализатор_классов , и queryset зависели от правил, основанных на разрешениях.

Вернуться на верх

source

permissions.py

Authentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.

— Apple Developer Documentation

Together with authentication and throttling, permissions determine whether a request should be granted or denied access.

Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the request.user and request.auth properties to determine if the incoming request should be permitted.

Permissions are used to grant or deny access for different classes of users to different parts of the API.

The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds to the IsAuthenticated class in REST framework.

A slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the IsAuthenticatedOrReadOnly class in REST framework.

How permissions are determined

Permissions in REST framework are always defined as a list of permission classes.

Before running the main body of the view each permission in the list is checked.
If any permission check fails, an exceptions.PermissionDenied or exceptions.NotAuthenticated exception will be raised, and the main body of the view will not run.

When the permission checks fail, either a «403 Forbidden» or a «401 Unauthorized» response will be returned, according to the following rules:

  • The request was successfully authenticated, but permission was denied. — An HTTP 403 Forbidden response will be returned.
  • The request was not successfully authenticated, and the highest priority authentication class does not use WWW-Authenticate headers. — An HTTP 403 Forbidden response will be returned.
  • The request was not successfully authenticated, and the highest priority authentication class does use WWW-Authenticate headers. — An HTTP 401 Unauthorized response, with an appropriate WWW-Authenticate header will be returned.

Object level permissions

REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.

Object level permissions are run by REST framework’s generic views when .get_object() is called.
As with view level permissions, an exceptions.PermissionDenied exception will be raised if the user is not allowed to act on the given object.

If you’re writing your own views and want to enforce object level permissions,
or if you override the get_object method on a generic view, then you’ll need to explicitly call the .check_object_permissions(request, obj) method on the view at the point at which you’ve retrieved the object.

This will either raise a PermissionDenied or NotAuthenticated exception, or simply return if the view has the appropriate permissions.

For example:

def get_object(self):
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
    self.check_object_permissions(self.request, obj)
    return obj

Note: With the exception of DjangoObjectPermissions, the provided
permission classes in rest_framework.permissions do not implement the
methods necessary to check object permissions.

If you wish to use the provided permission classes in order to check object
permissions, you must subclass them and implement the
has_object_permission() method described in the Custom
permissions
section (below).


Limitations of object level permissions

For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.

Often when you’re using object level permissions you’ll also want to filter the queryset appropriately, to ensure that users only have visibility onto instances that they are permitted to view.

Because the get_object() method is not called, object level permissions from the has_object_permission() method are not applied when creating objects. In order to restrict object creation you need to implement the permission check either in your Serializer class or override the perform_create() method of your ViewSet class.

Setting the permission policy

The default permission policy may be set globally, using the DEFAULT_PERMISSION_CLASSES setting. For example.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

If not specified, this setting defaults to allowing unrestricted access:

'DEFAULT_PERMISSION_CLASSES': [
   'rest_framework.permissions.AllowAny',
]

You can also set the authentication policy on a per-view, or per-viewset basis,
using the APIView class-based views.

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Or, if you’re using the @api_view decorator with function based views.

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

Note: when you set new permission classes via the class attribute or decorators you’re telling the view to ignore the default list set in the settings.py file.

Provided they inherit from rest_framework.permissions.BasePermission, permissions can be composed using standard Python bitwise operators. For example, IsAuthenticatedOrReadOnly could be written:

from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = [IsAuthenticated|ReadOnly]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Note: it supports & (and), | (or) and ~ (not).


API Reference

AllowAny

The AllowAny permission class will allow unrestricted access, regardless of if the request was authenticated or unauthenticated.

This permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.

IsAuthenticated

The IsAuthenticated permission class will deny permission to any unauthenticated user, and allow permission otherwise.

This permission is suitable if you want your API to only be accessible to registered users.

IsAdminUser

The IsAdminUser permission class will deny permission to any user, unless user.is_staff is True in which case permission will be allowed.

This permission is suitable if you want your API to only be accessible to a subset of trusted administrators.

IsAuthenticatedOrReadOnly

The IsAuthenticatedOrReadOnly will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the «safe» methods; GET, HEAD or OPTIONS.

This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.

DjangoModelPermissions

This permission class ties into Django’s standard django.contrib.auth model permissions. 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 model permissions assigned. The appropriate model is determined by checking get_queryset().model or queryset.model.

  • GET requests require the user to have the view or change 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.
  • DELETE requests require the user to have the delete permission on the model.

The default behaviour can also be overridden to support custom model permissions.

To use custom model permissions, override DjangoModelPermissions and set the .perms_map property. Refer to the source code for details.

DjangoModelPermissionsOrAnonReadOnly

Similar to DjangoModelPermissions, but also allows unauthenticated users to have read-only access to the API.

## DjangoObjectPermissions

This permission class ties into Django’s standard object permissions framework 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.

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.
  • DELETE requests require the user to have the delete permission on the model instance.

Note that DjangoObjectPermissions does not require the django-guardian package, and should support other object-level backends equally well.

As with DjangoModelPermissions you can use custom model permissions by overriding DjangoObjectPermissions and setting the .perms_map property. Refer to the source code for details.


Note: If you need object level view permissions for GET, HEAD and OPTIONS requests and are using django-guardian for your object-level permissions backend, you’ll want to consider using the DjangoObjectPermissionsFilter class provided by the djangorestframework-guardian2 package. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.


Custom permissions

To implement a custom permission, override BasePermission and implement either, or both, of the following methods:

  • .has_permission(self, request, view)
  • .has_object_permission(self, request, view, obj)

The methods should return True if the request should be granted access, and False otherwise.

If you need to test if a request is a read operation or a write operation, you should check the request method against the constant SAFE_METHODS, which is a tuple containing 'GET', 'OPTIONS' and 'HEAD'. For example:

if request.method in permissions.SAFE_METHODS:
    # Check permissions for read-only request
else:
    # Check permissions for write request

Note: The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call .check_object_permissions(request, obj). If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising PermissionDenied on failure.)


Custom permissions will raise a PermissionDenied exception if the test fails. To change the error message associated with the exception, implement a message attribute directly on your custom permission. Otherwise the default_detail attribute from PermissionDenied will be used. Similarly, to change the code identifier associated with the exception, implement a code attribute directly on your custom permission — otherwise the default_code attribute from PermissionDenied will be used.

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view):
         ...

Examples

The following is an example of a permission class that checks the incoming request’s IP address against a blocklist, and denies the request if the IP has been blocked.

from rest_framework import permissions

class BlocklistPermission(permissions.BasePermission):
    """
    Global permission check for blocked IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blocked = Blocklist.objects.filter(ip_addr=ip_addr).exists()
        return not blocked

As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Instance must have an attribute named `owner`.
        return obj.owner == request.user

Note that the generic views will check the appropriate object level permissions, but if you’re writing your own custom views, you’ll need to make sure you check the object level permission checks yourself. You can do so by calling self.check_object_permissions(request, obj) from the view once you have the object instance. This call will raise an appropriate APIException if any object-level permission checks fail, and will otherwise simply return.

Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you’ll need to filter the queryset separately. See the filtering documentation for more details.

Overview of access restriction methods

REST framework offers three different methods to customize access restrictions on a case-by-case basis. These apply in different scenarios and have different effects and limitations.

  • queryset/get_queryset(): Limits the general visibility of existing objects from the database. The queryset limits which objects will be listed and which objects can be modified or deleted. The get_queryset() method can apply different querysets based on the current action.
  • permission_classes/get_permissions(): General permission checks based on the current action, request and targeted object. Object level permissions can only be applied to retrieve, modify and deletion actions. Permission checks for list and create will be applied to the entire object type. (In case of list: subject to restrictions in the queryset.)
  • serializer_class/get_serializer(): Instance level restrictions that apply to all objects on input and output. The serializer may have access to the request context. The get_serializer() method can apply different serializers based on the current action.

The following table lists the access restriction methods and the level of control they offer over which actions.

queryset permission_classes serializer_class
Action: list global global object-level*
Action: create no global object-level
Action: retrieve global object-level object-level
Action: update global object-level object-level
Action: partial_update global object-level object-level
Action: destroy global object-level no
Can reference action in decision no** yes no**
Can reference request in decision no** yes yes

* A Serializer class should not raise PermissionDenied in a list action, or the entire list would not be returned.
** The get_*() methods have access to the current view and can return different Serializer or QuerySet instances based on the request or action.


Third party packages

The following third party packages are also available.

DRF — Access Policy

The Django REST — Access Policy package provides a way to define complex access rules in declarative policy classes that are attached to view sets or function-based views. The policies are defined in JSON in a format similar to AWS’ Identity & Access Management policies.

Composed Permissions

The Composed Permissions package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.

REST Condition

The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.

DRY Rest Permissions

The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app’s data model. It also supports permission checks being returned to a client app through the API’s serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.

Django Rest Framework Roles

The Django Rest Framework Roles package makes it easier to parameterize your API over multiple types of users.

Rest Framework Roles

The Rest Framework Roles makes it super easy to protect views based on roles. Most importantly allows you to decouple accessibility logic from models and views in a clean human-readable way.

Django REST Framework API Key

The Django REST Framework API Key package provides permissions classes, models and helpers to add API key authorization to your API. It can be used to authorize internal or third-party backends and services (i.e. machines) which do not have a user account. API keys are stored securely using Django’s password hashing infrastructure, and they can be viewed, edited and revoked at anytime in the Django admin.

Django Rest Framework Role Filters

The Django Rest Framework Role Filters package provides simple filtering over multiple types of roles.

Django Rest Framework PSQ

The Django Rest Framework PSQ package is an extension that gives support for having action-based permission_classes, serializer_class, and queryset dependent on permission-based rules.

Понравилась статья? Поделить с друзьями:
  • Django nginx 500 internal server error
  • Django models error messages
  • Django migrations error
  • Django login form error
  • Django logging error 500