问题
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?
回答1:
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