简体   繁体   English

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

[英]Class-based views: where to check for permissions?

I am not very comfortable using class-based views but I am aware of their perks so I am forcing myself to start using them more often. 我对使用基于类的视图不太满意,但是我知道它们的好处,因此我强迫自己开始更频繁地使用它们。

There's this view that receives a path param: manage/:id to manage a particular entity. 该视图接收路径参数: 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

An Entity includes a list of authorized users to perform special actions. Entity包括执行特殊操作的授权用户列表。 This view, MyView is one of those special actions. 在此视图中, MyView是这些特殊操作之一。

I tried making a decorator for the view but it required finding the Entity first so I wasn't sure how to work that out. 我尝试为视图制作装饰器,但是它需要首先找到Entity所以我不确定如何解决这个问题。

Now, I have a check_permission(request, entity) function that checks if the current user is one of these authorized ones. 现在,我有一个check_permission(request, entity)函数,该函数检查当前用户是否是这些授权用户之一。

My question is where should I call this function in the class-based views like MyView which will be any of these views considered "special actions"? 我的问题是,在像MyView这样的基于类的视图中,应将这些函数中的任何一个视为“特殊动作”,在哪里调用该函数?

Should I call it just from get_context_data() ? 我应该只从get_context_data()调用它吗?

put it into dispatch() . 将其放入dispatch() It could look like this: 它可能看起来像这样:

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)

Take a look at Django Braces , it's a solid set of mixins which are designed around permissions. 看一下Django Braces ,它是一组围绕权限设计的混合类。

How specifically you deal with permissions depends largely on implementation. 具体处理权限的方式很大程度上取决于实现。 I've done it in dispatch() before which is the way Braces does it but if it's specific to an object or queryset, I'll do it in the actual get_object or get_queryset methods as part of a DetailView. 我已经在dispatch()中完成了,这是大括号执行的方式,但是如果特定于对象或查询集,我将在DetailView的实际get_object或get_queryset方法中进行。

For example if you had a creator associated with an Entity, you could override get_object to check the current logged in user is the Entity's creator. 例如,如果您有一个与实体相关联的创建者,则可以覆盖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
        )

Note: LoginRequiredMixin is a part of Braces. 注意:LoginRequiredMixin是括号的一部分。 Very slick. 很好吃

You can check permissions in the dispatch as yedpodtrzitko has said. 您可以按照yedpodtrzitko所说的在dispatch检查权限。 I think it's also a good idea to throw it inside of a mixin that you can put on your views. 我认为将其放入可放入视图的mixin中也是一个好主意。

Here's an example: 这是一个例子:

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

Now you can throw MyCustomPermissionMixin on your view: 现在,您可以在视图上抛出MyCustomPermissionMixin

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

In your case, since you're using a TemplateView , you should also make a get_object() method that returns the object that you want to deal with. 在您的情况下,由于使用的是TemplateView ,因此还应该创建一个get_object()方法,该方法返回要处理的对象。 Template views don't have this method by default. 模板视图默认情况下没有此方法。

Finally, just want to say that you will love Django's class based views once you learn some more about how to use them. 最后,只想说一旦您了解了更多关于Django的基于类的视图的用法,便会喜欢上它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM