On May 18, 2013, at 8:57 AM, Marc Tamlyn <marc.tam...@gmail.com> wrote:

> 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?

I'm sure I have it somewhere, but knowing where is another thing all together ;)

If I recall I made a mixin superclass that added an ``as_decorator()`` class 
function which functioned similarly to the ``as_view()`` function. It took a 
common entry point and generated a non class function based on that and 
returned it.

As far as the actual mixins themselves I'd take a look at django-braces which 
has implementations of a lot of the decorators as mixins already they'd just 
need maybe some tweaking and then code added to allow turning them into actual 
decorators.

> 
> 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.
>  
>  


-----------------
Donald Stufft
PGP: 0x6E3CBCE93372DCFA // 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to