Hi,

On Sep 16, 2011, at 12:11 AM, Łukasz Rekucki wrote:

Hi,

On 15 September 2011 22:44, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:

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

As the ticket creator I feel obligated to reply :)

Me (as the poster of the latest patch) too :)

Thinking about it now, it does look kinda ugly. It's mainly because I
was focus on how to reuse existing decorators in CBV context. It
shouldn't be to hard  to make the "view_decorator" a meta-decorator
(or a factory function as you call it) that turns login_required to
something that is both a class and function decorator. Methods are
still out-of-bounds for non-runtime introspection, but after almost 1
year of using CBV, I never needed to decorate a method.

I would like to also comment on the new approach in that ticket.
Making a shallow copy of a class is *MAGIC* to me. It breaks the basic
invariant "issubsclass(decorator(A), A) == True". This is important if
you're planing to use this as "B = decorator()(A)" (and you are,
'cause the whole point of not modifying the original class is to allow
safely doing this), as you quickly end up with weird alternate
hierarchies. So, please don't do that :)

I agree that in an ideal world we'd have a better solution. On the other hand, the cbv-decorator using inheritance just didn't work, and the one using shallow copies does (if you don't use B=decorator()(A), indeed).

As Donald mentioned, the more elegant solution for classes is to use base classes (mixins) instead of class decorators. I'm not sure though if every decorator can be replaced by a mixin, and if the order of these mixins can be arbitrary in that case (which I believe is desirable). Can anybody comment on that?

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

+1 on this. I would be a bit concerned about this vs. future
implementation of generator-based-views that allow some kind of
response streaming (is someone working on that?).

I've written a proof-of-concept patch to @login_required (well,
@user_passes_test, actually):

   https://gist.github.com/1220375

Did I already mention creating a subclass in the class decorator
breaks super ;) [https://gist.github.com/643536]

Can I get some thoughts on this technique and some feedback on whether
it's OK to apply to every decorator built into Django?

It would be great to have that meta-decorator, so everyone else could
upgrade their decorators just by decorating them.

If this doesn't exist, then the view_decorator still has a right to live.

So what would have to be created is a meta-decorator universal_decorator, replacing or using view_decorator, such that universal_decorator(login_required) is the actual universal decorator. This would be applied to all django-decorators, but I think it would be good to also allow applying universal_decorator to an already universal decorator, such that:

    # after this...
    login_required = universal_decorator(login_required)
    # ... this will hold
    assert login_required == universal_decorator(login_required)







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

Reply via email to