I am playing around with the djangorestframework
and my goal is to use DjangoModelPermissions
on my view which reacts to a GET
request. The official documentation says:
The default behavior can also be overridden to support custom model permissions. For example, you might want to include a
view
model permission forGET
requests.
Source
So I modified my model like the following:
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
And the view:
class UserListAPIView(ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.DjangoModelPermissions,)
Settings:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissions'
]
}
The problem is that my implemented UserListAPIView
successfully returns a list of all objects to a user who doesn't belong to a Group
neither has any custom User Permission
. It seems to me that the DjangoModelPermissions
takes no effect.
DjangoModelPermissions allows us to set any combination of permissions to each of the users separately. The permission then checks if the user is authenticated and if they have add , change , or delete user permissions on the model.
Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The permission and throttling policies can then use those credentials to determine if the request should be permitted.
@Yannic Hamann's solution has a small bug. It overwrites parent's perms_map['GET'].
As follows, A dictionary overring need 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']
dictionary overring test
class Parent:
perms = {'GET':'I am a Parent !'}
class Child(Parent):
def __init__(self):
self.perms['GET'] = 'I am a Child !'
dictionary overring result
>>> 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.
^^^^^
Ouch, that was easier than I thought:
class CustomDjangoModelPermission(permissions.DjangoModelPermissions):
def __init__(self):
self.perms_map = copy.deepcopy(self.perms_map) # from EunChong's answer
self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With