I'm going to resurrect this old thread as I'd like to get it resolved in some fashion.
I used to be very in favour of the class decorators approach. I've been using an implementation of `@class_view_decorator(func)` for some time and it works pretty well. That said my implementation at least was subject to a notable flaw which is that if multiple parts of the hierarchy have the same decorator applied to them then the check gets done twice. Mixins are much cleverer than this because of MRO, so we avoid that problem. Mixins however have their own issues - it's "harder" (for some definition) to ensure that all of your top-level permission checking happening in the correct order. That said, I am certainly veering towards implementing this using mixins (for each piece of functionality). I'd really like to have a look at Donald's implementation, sadly it seems to no longer be on github. Do you still have then code somewhere, or can you explain the implementation idea? Marc On Thursday, 15 September 2011 22:44:39 UTC+2, Jacob Kaplan-Moss wrote: > > Hi folks -- > > I'd like to convert all the view decorators built into Django to be > "universal" -- so they'll work to decorate *any* view, whether a > function, method, or class. I believe I've figured out a technique for > this, but I'd like some feedback on the approach before I dive in too > deep. > > Right now view decorators (e.g. @login_required) only work on > functions. If you want to use a decorator on a method then you need to > "convert" the decorator using method_decorator(original_decorator). > You can't use view decorators on class-based views at all. This means > making a class-based view require login requires this awesomeness:: > > class MyView(View): > @method_decorator(login_required) > def dispatch(self, *args, **kwargs): > return super(MyView, self.dispatch(*args, **kwargs) > > This makes me sad. It's really counter-intuitive and relies on a > recognizing that functions and methods are different to even know to > look for method_decorator. > > #14512 proposes a adding another view-decorator-factory for decorating > class-based views, which would turn the above into:: > > @class_view_decorator(login_required) > class MyView(View): > ... > > This makes me less sad, but still sad. Factory functions. Ugh. > > I want @login_required to work for anything:: > > @login_required > class MyView(View): > ... > > class Something(object): > @login_required > def my_view(self, request): > ... > > @login_required > def my_view(request): > ... > > > Now, back in the day we somewhat had this: decorators tried to work > with both functions and methods. The technique turned out not to work > (see #12804) and was removed in [12399]. See > > http://groups.google.com/group/django-developers/browse_thread/thread/3024b14a47f5404d > for the discussion. > > I believe, however, I've figured out a different technique to make > this work: don't try to detect bound versus unbound methods, but > instead look for the HttpRequest object. It'll either be args[0] if > the view's a function, or args[1] if the view's a method. This > technique won't work for any old decorator, but it *will* work (I > think) for any decorator *designed to be applied only to views*. > > I've written a proof-of-concept patch to @login_required (well, > @user_passes_test, actually): > > https://gist.github.com/1220375 > > The test suite passes with this, with one exception: > > https://code.djangoproject.com/browser/django/trunk/tests/regressiontests/decorators/tests.py#L87 > . > I maintain that this test is broken and should be using RequestFactory > instead. > > Can I get some thoughts on this technique and some feedback on whether > it's OK to apply to every decorator built into Django? > > Jacob > > -- You received this message because you are subscribed to the Google Groups "Django developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to django-developers@googlegroups.com. Visit this group at http://groups.google.com/group/django-developers?hl=en. For more options, visit https://groups.google.com/groups/opt_out.