Django Rest Framework在ListAPIView上使用DjangoModelPermissions

时间:2017-10-05 11:37:05

标签: python django django-rest-framework

我正在使用djangorestframework,我的目标是在我的视图上使用DjangoModelPermissions,这会对GET请求作出反应。官方文件说:

  

也可以覆盖默认行为以支持自定义模型   权限。例如,您可能希望包含view模型   GET请求的权限。

Source

所以我修改了我的模型,如下所示:

class User(AbstractUser):
    display_name = models.CharField(_('Display Name'), blank=True, max_length=255)

    class Meta:
        permissions = (
            ("view_user", "Can view users"),
        )

    def __str__(self):
        return self.username

观点:

class UserListAPIView(ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.DjangoModelPermissions,)

设定:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissions'
    ]
}

问题在于,我实施的UserListAPIView成功地向不属于Group且没有任何自定义User Permission的用户返回了所有对象的列表。在我看来DjangoModelPermissions没有任何效果。

3 个答案:

答案 0 :(得分:3)

哎呀,这比我想象的容易:

class CustomDjangoModelPermission(permissions.DjangoModelPermissions):

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

答案 1 :(得分:2)

@Yannic Hamann的解决方案有一个小错误。它会覆盖父母的perms_map ['GET']。

如下所示,字典覆盖需要深度复制。

class CustomDjangoModelPermission(permissions.DjangoModelPermissions):

    def __init__(self):
        self.perms_map = copy.deepcopy(self.perms_map) # you need deepcopy when you inherit a dictionary type 
        self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']

  

字典覆盖测试

class Parent:
    perms = {'GET':'I am a Parent !'}

class Child(Parent):
    def __init__(self):
        self.perms['GET'] = 'I am a Child !'
  

词典覆盖结果

>>> print(Parent().perms['GET'])
I am a Parent !

>>> print(Child().perms['GET'])
I am a Child !

>>> print(Parent().perms['GET'])
I am a Child ! # Parent's perms is overwritten by Child.
       ^^^^^  

答案 2 :(得分:0)

您必须覆盖客户DjangoModelPermissions。

class BaseModelPerm(permissions.DjangoModelPermissions):

     def get_custom_perms(self, method, view):
          app_name = view.model._meta.app_label
          return [app_name+"."+perms for perms in view.extra_perms_map.get(method, [])]

    def has_permission(self, request, view):
       perms = self.get_required_permissions(request.method, view.model)
       perms.extend(self.get_custom_perms(request.method, view))
       return (
          request.user and
          (request.user.is_authenticated() or not self.authenticated_users_only) and
        request.user.has_perms(perms)
    )
您可以在视图中使用

,如下所示

class ViewName(generic.ListApiView):

      """ Trip listing view """

     model = model_name
     serializer_class = serializer_class
     permission_classes = (permissions.IsAuthenticated,BaseModelPerm)
     queryset = model.objects.all()
     extra_perms_map = {
      'GET': ["can_view_trip"],
     }

添加您要添加​​的任何额外权限。