Django Rest Framework在ListAPIView上使用DjangoModelPermissions

Yan*_*ann 3 python django django-rest-framework

我正在玩djangorestframework,我的目标是在DjangoModelPermissionsGET请求做出反应的视图上使用。官方文件说:

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

资源

因此,我如下修改了我的模型:

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
Run Code Online (Sandbox Code Playgroud)

和视图:

class UserListAPIView(ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.DjangoModelPermissions,)
Run Code Online (Sandbox Code Playgroud)

设定:

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

问题是我的实现UserListAPIView成功地将所有对象的列表返回给不属于Group自定义对象的用户User Permission。在我看来,这DjangoModelPermissions没有效果。

Eun*_*Lee 7

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

如下,A 字典覆盖需要 deepcopy。

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']
Run Code Online (Sandbox Code Playgroud)

字典覆盖测试

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

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

字典覆盖结果

>>> 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.
       ^^^^^  
Run Code Online (Sandbox Code Playgroud)


Yan*_*ann 5

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

class CustomDjangoModelPermission(permissions.DjangoModelPermissions):

    def __init__(self):
        self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']
Run Code Online (Sandbox Code Playgroud)