3

The docs feature nice options for applying decorators such as login_required to Class Based Views.

However, I'm a little unclear about how to pass specific arguments along with the decorator, in this case I'd like to change the login_url of the decorator.

Something like the following, only valid:

@login_required(login_url="Accounts:account_login")
@user_passes_test(profile_check)
class AccountSelectView(TemplateView):
    template_name='select_account_type.html'
Adam Starrh
  • 6,428
  • 8
  • 50
  • 89
  • As well as changing the way you use the decorator, you need to reverse the login url. As you're using it in a decorator, use `reverse_lazy`, i.e. `login_url=reverse_lazy("Accounts:account_login")`. – Alasdair Nov 27 '15 at 09:30

1 Answers1

4

You should use @method_decorator with class methods:

A method on a class isn’t quite the same as a standalone function, so you can’t just apply a function decorator to the method – you need to transform it into a method decorator first. The method_decorator decorator transforms a function decorator into a method decorator so that it can be used on an instance method.

Then just call decorator with arguments you need and pass it to method decorator (by calling decorator function that can accept arguments you will get actual decorator on exit). Don't forget to pass the name of the method to be decorated as the keyword argument name (dispatch for example) if you will decorate the class instead of class method itself:

@method_decorator(login_required(login_url="Accounts:account_login"),
                  name='dispatch')
@method_decorator(user_passes_test(profile_check), name='dispatch')
class AccountSelectView(TemplateView):
    template_name='select_account_type.html'
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • 2
    I'm importing `from django.utils.decorators import method_decorator` but this solution produces an error: `"TypeError: method_decorator() got an unexpected keyword argument 'name'` – Adam Starrh Nov 27 '15 at 21:14
  • Ah, I simply need to update to Django 1.9! Thanks very much. – Adam Starrh Nov 27 '15 at 21:17
  • How to do that on Django 1.8 ? – alanjds Aug 11 '16 at 18:23
  • @alanjds there is method_decorator in 1.8 but in docs there is no info about ability to decorate class itself... Try to decorate method in class – ndpu Aug 11 '16 at 19:04
  • Had copied over from 1.9 to local utils module. Worked. The point I liked about the ``name`` is to not have to override the inner method. Thanks anyway. – alanjds Aug 11 '16 at 19:52
  • `name` accepts the `method name` from `CBV` on which we want to apply the decorator. I would like to apply it on whole class which includes two method `get` and `put`, but `name` accepts only single arg as `string`. How can this be extended further? and `name='dispatch` gives `AnonymousUser` – neferpitou Jul 10 '20 at 14:12