Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between the two methods of decorating class-based views?

I'm writing a view that inherits from ListView, and am trying to restrict the view to logged-in users.

https://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating-in-urlconf says that decorating with login_required in the URLconf "applies the decorator on a per-instance basis. If you want every instance of a view to be decorated, you need to take a different approach" -that approach being to decorate the dispatch method in the view code.

I thought I knew the difference between a class and an instance but this phrase doesn't mean anything to me. Could someone clarify? Apart from having a decorator in the URLconf as opposed to in your class definition, what are the differences between the two approaches?

The paragraph above that link seems to answer the question: "Since class-based views aren't functions, decorating them works differently depending on if you're using as_view or creating a subclass."

Really?? I seem to be able to use the URLconf approach with my subclass of ListView.

like image 370
mr_c Avatar asked Aug 26 '12 18:08

mr_c


1 Answers

Imagine you have the following class based view:

class PostListView(ListView):
     model = Post

ProtectedPostListView = login_required(PostListView.as_view())

and your urls.py:

url(r'posts$', ProtectedPostListView)

If you use this approach then you lose the ability to subclass ProtectedPostListView e.g

class MyNewView(ProtectedPostListView):
    #IMPOSSIBLE

and this is because the .as_view() returns a function and after applying the login_required decorator you are left with a function, so subclassing is not possible.

On the other hand if you go with the second approach i.e use the method decorator the subclassing is possible. e.g

class PostListView(ListView):
     model = Post

     @method_decorator(login_required)
     def dispatch(self, *args, **kwargs):
         return super(PostListView, self).dispatch(*args, **kwargs)

class MyNewView(PostListView):
     #LEGAL
like image 180
thikonom Avatar answered Oct 12 '22 23:10

thikonom