Django: authenticate based on an object's properties using class-based views

只谈情不闲聊 提交于 2020-01-23 14:40:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!