Django mixins用于基于类的通用视图

时间:2016-04-15 05:23:24

标签: django django-views mixins

我正在尝试实现staff_member_required mixins:

以下是我发现的两种方法:

首先:

class StaffRequiredMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_staff:
            messages.error(
                request,
                'You do not have the permission required to perform the '
                'requested operation.')
            return redirect(settings.LOGIN_URL)
        return super(StaffRequiredMixin, self).dispatch(request,
            *args, **kwargs)

第二

class StaffRequiredMixin(object):
    @classmethod
    def as_view(self, *args, **kwargs):
        view = super(StaffRequiredMixin, self).as_view(*args, **kwargs)
        return staff_member_required(view)

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_staff:
            messages.error(
                request,
                'You do not have the permission required to perform the '
                'requested operation.')
            return redirect(settings.LOGIN_URL)
        return super(StaffRequiredMixin, self).dispatch(request,
            *args, **kwargs)

我想知道的是:

  1. 为什么第二种方法是覆盖as_view()方法并用staff_member_required包裹它?

  2. 这样做是否可以获得任何“额外”优势?

  3. 我是这些mixins的新手。请帮忙。

1 个答案:

答案 0 :(得分:4)

TL; DR: they're close to the same, the difference is in checking is_active as well as is_staff and the error messages. You probably don't need both because the as_view override negates the need for the dispatch override anyway.

These are really just two ways of doing close to the same thing.

This code:

class StaffRequiredMixin(object):
    @classmethod
    def as_view(self, *args, **kwargs):
        view = super(StaffRequiredMixin, self).as_view(*args, **kwargs)
        return staff_member_required(view)

...could actually be used alone to implement the staff_member_required decorator. In this case the staff_member_required functionality gets called in the view's as_view() function (i.e., from as_view() in your URLConf).

This code:

class StaffRequiredMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_staff:
            messages.error(
                request,
                'You do not have the permission required to perform the '
                'requested operation.')
            return redirect(settings.LOGIN_URL)
        return super(StaffRequiredMixin, self).dispatch(request,
            *args, **kwargs)

...filters users in the dispatch method. You can see in the Django codebase that as_view actually calls dispatch. This means that if you use both together you won't actually ever trigger the if not request.user.is_staff code in the dispatch method because any user who doesn't pass would have been filtered out in the as_view method.

The second difference is that staff_member_required is slightly different from what the first code does. If you check out the code, you'll notice that staff_member_required also checks whether the user's is_active flag passes (not just is_staff like in your dispatch decorator). It also doesn't pass the messages.error like in your code.