serialize permission

126 views
Skip to first unread message

Richard Tier

unread,
Jan 13, 2014, 7:10:52 PM1/13/14
to django-res...@googlegroups.com

I would like to serialize object level permission - and send a simple True or False to the browser - so accordingly I trigger the "allow editing" code.

I am doing this so the user does not have functionality presented to them that they cannot use.

Is there a built in way to do this? The docs do not allude to this.

I have attempted the following on the serializer:

has_permission = serializers.SerializerMethodField('check_permission')

def check_permission(self, obj):
    return self.check_object_permissions(self.request, obj)

but the serializer does not have the method check_object_permissions - that belongs to the permission object.

jay...@linear3d.com

unread,
Jan 20, 2014, 5:15:01 PM1/20/14
to django-res...@googlegroups.com
The object permissions are a property of the view layer, not the serializer.  Additionally the permissions can be different for each HTTP verb, so a single boolean value may not be sufficient.

I had a similar problem to solve recently and the method on the serializer looked something like this:

    def check_permissions(self, obj, viewset, func):
        """
        Returns a dict with the permissions values for each HTTP method that the
        function responds to.  If no function is passed it returns the permission
        values for the related ViewSet.
        May return incorrect values if the permission_classes utilize the
        HTTP_REFERER or PATH_INFO components of the request object.
        """
        if hasattr(func, 'kwargs') and 'permission_classes' in func.kwargs:
            permission_classes = func.kwargs['permission_classes']
        else:
            permission_classes = viewset.permission_classes

        request = copy.copy(self.context['request'])

        if hasattr(func, 'bind_to_methods'):
            methods = func.bind_to_methods
        else:
            methods = ("get", "post", "put", "patch", "delete")

        permissions = {method:True for method in methods}
    
        for permission_class in permission_classes:
            permission = permission_class()
            for method in methods:
                if permissions[method]:
                    request.META['REQUEST_METHOD'] = method
                    request._method = method.upper()
                    permissions[method] = permission.has_permission(request, None) and \
                                          permission.has_object_permission(request, None, obj)

        return permissions

The code above is specific for ViewSets, it would be a bit simpler to implement for regular API views.

Richard Tier

unread,
Jan 23, 2014, 4:58:34 PM1/23/14
to django-res...@googlegroups.com
thats great - thanks for the help.

Richard Tier

unread,
Jan 24, 2014, 8:31:36 PM1/24/14
to django-res...@googlegroups.com
for clarity - how are you calling this function from the serializer? I tried:

# on serializer
    has_permission = serializers.SerializerMethodField('check_permissions')

        def check_permissions(self, obj, viewset, function):
            ....

but this results in error as SerializerMethodField pases self and object, but now viewset.

Im guessing you don't use SerializerMethodField?

Jay Cox

unread,
Jan 27, 2014, 5:17:02 PM1/27/14
to django-res...@googlegroups.com
The check_permissions method I sent is more of a helper method.

For use with the SerializerMethodField you should probably wrap it in a function looking something like this:

def permissions_for_foo(self, obj):
    from views import MyViewSet  # import inside method to avoid circular dependency
    return self.check_permissions(obj, MyViewSet, MyViewSet.foo)


That is not necessarily the best way to deal with the circular dependency issue, but it is the simplest in this context.


--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply all
Reply to author
Forward
0 new messages