Multiple decorators for a view in Django: Execution order

后端 未结 4 2030
温柔的废话
温柔的废话 2020-12-24 01:31

I am trying to decorate a Django view by two decorators, one for checking login, and one for checking is_active.

The first one is the built-in @login_required<

相关标签:
4条回答
  • 2020-12-24 02:27

    Now, the decorators in Python work from the inside out

    Well I guess that depends on your definition of inside out. In your case, you want @login_required to execute first, and so it should be the "outermost" (top) decorator.

    As you noted, your last example works, and is indeed the correct way to do this.

    edit

    The confusion might be how these particular decorators work.

    @login_required(@original_view) returns a new view, which first checks if you are logged in, and then calls original_view

    so

    
        @login_required(
            @active_required(
                @my_view
            )
        )
    
    first checks if you are logged in, then
        first(second) checks if you are active, then
            runs my_view
    
    0 讨论(0)
  • 2020-12-24 02:29

    To explain it a bit more (I was also confused at first): active_required is applied first in a sense that it takes my_view and wraps it in some code. Then login_required is applied and wraps the result in some more code.

    But when this wrapped version of my_view is actually invoked, first the code added by login_required is executed (checking that you're logged in), then the code added by active_required is executed (checking that you're active) and then finally my_view is executed.

    0 讨论(0)
  • 2020-12-24 02:33

    Decorators are applied in the order they appear in the source. Thus, your second example:

    @login_required
    @active_required
    def foo(request):
        ...
    

    is equivalent to the following:

    def foo(request):
        ...
    foo = login_required(active_required(foo))
    

    Thus, if the code of one decorator depends on something set by (or ensured by) another, you have to put the dependent decorator "inside" the depdended-on decorator.

    However, as Chris Pratt notes, you should avoid having decorator dependencies; when necessary, create a single new decorator that calls both in the right order.

    0 讨论(0)
  • 2020-12-24 02:33

    It only really makes sense to stack decorators if they have truly unique functionality. Based on your description, there's never going to be a scenario where you will want to use active_required but not login_required. Therefore, it makes more sense to have a login_and_active_required decorator that checks both and branches accordingly. Less to type, less to document, and negates the problem.

    0 讨论(0)
提交回复
热议问题