如何自定义DjangoModelPermissions来拒绝GET、HEAD和OPTIONS请求

mwngjboj  于 2023-04-07  发布在  Go
关注(0)|答案(3)|浏览(93)

如果用户没有权限,我需要拒绝对View的所有访问,但 DjangoModelPermissions 只拒绝POST,PUT,PATCH和DELETE。如何做到?

0yycz8jy

0yycz8jy1#

其他两个选项是修补:

django_view_permissions = ['%(app_label)s.view_%(model_name)s']
permissions.DjangoModelPermissions.perms_map['GET'] = django_view_permissions
permissions.DjangoModelPermissions.perms_map['OPTIONS'] = django_view_permissions
permissions.DjangoModelPermissions.perms_map['HEAD'] = django_view_permissions

或子类化:

class ActualDjangoModelPermissions(permissions.DjangoModelPermissions):
    view_permissions = ['%(app_label)s.view_%(model_name)s']

    perms_map = {
        'GET': view_permissions,
        'OPTIONS': view_permissions,
        'HEAD': view_permissions,
        'POST': permissions.DjangoModelPermissions.perms_map['POST'],
        'PUT': permissions.DjangoModelPermissions.perms_map['PUT'],
        'PATCH': permissions.DjangoModelPermissions.perms_map['PATCH'],
        'DELETE': permissions.DjangoModelPermissions.perms_map['DELETE'],
    }

我更喜欢子类化

w3nuxt5m

w3nuxt5m2#

我只是添加了一个新的权限类,并更改了函数GET权限,如下所示:

"""
Provides a set of pluggable permission policies.
"""
from django.http import Http404

from rest_framework import exceptions

from rest_framework.permissions import BasePermission

class CustomDjangoModelPermissions(BasePermission):
    #copied from DjangoModelPermissions

    # Map methods into required permission codes.
    # Override this if you need to also provide 'view' permissions,
    # or if you want to provide custom permission codes.
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'], #permission changed
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    authenticated_users_only = True

    def get_required_permissions(self, method, model_cls):
        """
        Given a model and an HTTP method, return the list of permission
        codes that the user is required to have.
        """
        kwargs = {
            'app_label': model_cls._meta.app_label,
            'model_name': model_cls._meta.model_name
        }

        if method not in self.perms_map:
            raise exceptions.MethodNotAllowed(method)

        return [perm % kwargs for perm in self.perms_map[method]]

    def _queryset(self, view):
        assert hasattr(view, 'get_queryset') \
            or getattr(view, 'queryset', None) is not None, (
            'Cannot apply {} on a view that does not set '
            '`.queryset` or have a `.get_queryset()` method.'
        ).format(self.__class__.__name__)

        if hasattr(view, 'get_queryset'):
            queryset = view.get_queryset()
            assert queryset is not None, (
                '{}.get_queryset() returned None'.format(view.__class__.__name__)
            )
            return queryset
        return view.queryset

    def has_permission(self, request, view):
        # Workaround to ensure DjangoModelPermissions are not applied
        # to the root view when using DefaultRouter.
        if getattr(view, '_ignore_model_permissions', False):
            return True

        if not request.user or (
           not request.user.is_authenticated and self.authenticated_users_only):
            return False

        queryset = self._queryset(view)
        perms = self.get_required_permissions(request.method, queryset.model)

        return request.user.has_perms(perms)
06odsfpq

06odsfpq3#

比其他答案更简洁的版本是:

class CustomDjangoModelPermission(permissions.DjangoModelPermissions):

    def __init__(self):
        self.perms_map = copy.deepcopy(self.perms_map)
        self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']

来源:This SO answer
这只会改变GET请求,你也可以很容易地改变你想要限制的其他方法。

相关问题