Let's say my app is like a forum, but that each post has a group of people which may see it.
SecretPost(Model):
can_see = myapp.main.models.GroupOfUsers()
I want to write a view which restricts users' access to these posts, and I'd prefer to use decorators, since that's how I've been handling access control everywhere else.
SecretPostView(DetailView):
"""Can only be seen by members of its group"""
@method_decorator(part_of_its_group)
def dispatch(self, request, *args, **kwargs):
return super(SecretPostView, self).dispatch(request, *args, **kwargs)
But when dispatch()
is called, I don't know anything about the object. Is there a good/idiomatic way to restrict user access after the object has already been retrieved?
You can access self
inside the method decorator, so you do have access to the current object calling self.get_object()
.
Anyway, if you are only using this behavior on generic views, you're probably better off creating a mixin that implement the dispatch
method (or could be the get_object
method) and does the check there, for example (using a little of imagination since idk how your groups are defined, maybe you are using django.contrib.auth groups):
class GroupRestrictionMixin(object):
group_field = 'group'
def dispatch(request, *args, **kwargs):
self.request = request
self.args = args
self.kwargs = kwargs
obj_group = getattr(self.get_object(), self.group_field)
user_groups = request.user.groups
if obj_group not in user_groups:
raise PermissionDenied
return super(GroupRestrictionMixin, self).dispatch(request, *args, **kwargs)
Then you can create any view that needs that behavior using your mixin:
class SecretPostView(GroupRestrictionMixin, DetailView):
pass
Idk if it's what you would call "idiomatic", but that's the easier way that comes to mind to keep it simple and reusable.
EDIT: the request, args and kwargs must be setted here so the get_object
method haves access to them. It gets a little uglier (you gotta repeat some code that's on the base dispatch
method), but still works :F
来源:https://stackoverflow.com/questions/15181622/django-authenticate-based-on-an-objects-properties-using-class-based-views