基于类的视图:在哪里检查权限?

时间:2017-01-18 17:04:19

标签: python django

我不习惯使用基于类的视图,但我知道他们的特权,所以我强迫自己开始更频繁地使用它们。

这个视图接收路径参数:manage/:id来管理特定实体。

class MyView(TemplateView):
  template_name = '...'

  def get_context_data(self, **kwargs):
    context = super(MyView, self).get_context_data(**kwargs)
    context['entity'] = get_object_or_404(Entity, pk=self.args[0])
    return context

Entity包括执行特殊操作的授权用户列表。此视图MyView是其中一项特殊操作。

我尝试为视图制作一个装饰器,但它需要先找到Entity,所以我不知道如何解决这个问题。

现在,我有一个check_permission(request, entity)函数,用于检查当前用户是否是这些授权用户之一。

我的问题是我应该在基于类的视图中调用此函数,例如MyView这些视图中的任何一个被视为“特殊操作”吗?

我应该只从get_context_data()拨打电话吗?

3 个答案:

答案 0 :(得分:3)

将其放入dispatch()。它看起来像这样:

class MyView(TemplateView):
   template_name = '...'

   def dispatch(self, request, *args, **kwargs):
       entity = get_object_or_404(Entity, pk=args[0])
       if not check_permission(request, entity):
           raise Http404
       return super(MyView, self).dispatch(request, *args, **kwargs)

答案 1 :(得分:1)

您可以检查dispatch中的权限,因为yedpodtrzitko已经说过了。我认为将它放在一个可以放在你的观点上的mixin中也是一个好主意。

以下是一个例子:

from django.core.exceptions import PermissionDenied


class ViewPermissionsMixin(object):
    """Base class for all custom permission mixins to inherit from"""
    def has_permissions(self):
        return True 

    def dispatch(self, request, *args, **kwargs):
        if not self.has_permissions():
            raise PermissionDenied
        return super(ViewPermissionsMixin, self).dispatch(
            request, *args, **kwargs)

class MyCustomPermissionMixin(ViewPermissionsMixin):

    def has_permissions(self):
        # here you will have access to both
        # self.get_object() and self.request.user
        return self.request.user in self.get_object().special_list_of_people

现在你可以在你的观点上抛出MyCustomPermissionMixin

class MyView(MyCustomPermissionMixin, TemplateView):
    # ...

在您的情况下,由于您使用的是TemplateView,因此您还应该创建一个get_object()方法来返回您要处理的对象。默认情况下,模板视图没有此方法。

最后,只想说一旦你学会了如何使用它们,你就会喜欢Django的基于类的观点。

答案 2 :(得分:0)

看看Django Braces,这是一组围绕权限设计的可靠的mixin。

您处理权限的具体方式在很大程度上取决于实施。我已经在dispatch()中完成了它,之前是Braces的方式,但如果它是特定于对象或查询集的,我将在实际的get_object或get_queryset方法中作为DetailView的一部分进行。

例如,如果您有与实体关联的创建者,则可以覆盖get_object以检查当前登录用户是实体的创建者。

class EntityView(LoginRequiredMixin, DetailView):
    model = Thing

    def get_object(self, **kwargs):
        return Entity.objects.get_object_or_404(
            pk=kwargs['entity_id'], 
            creator=self.request.user
        )

注意:LoginRequiredMixin是Braces的一部分。非常光滑。