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 post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.