On Thu, Sep 15, 2011 at 6:27 PM, Donald Stufft <donald.stu...@gmail.com>wrote:

> Gonna add this in here as well as ticket #14512
>
> I think using decorators to modify the way a CBV behaves is the wrong way
> to go about it, my reasoning is:
>
> 1) Decorators on functions make sense, since the only way to modify a
> function is to wrap it, so decorators provide a shortcut to do so.
>
> 2) There's already a standard way to add functionality to a class that has
> existed for a long time, is well tested, and as a bonus is something that
> people new to python but not new to programming will understand immediately.
>

I like the arguments here. On the other hand, I like Jacob's

«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»

So what about providing something roughly like:

###
class LoginRequired():
    # magic to check for user credentials, in a CBV style
    ...
    def __call__(self, wrap_me):
        # standard magic to apply the CBV decoration to a standard function
        # This might also include Jacob's trick to work with methods too
        ...

login_required = LoginRequired # backwards compatibility
###

Actually that implementation of __call__ is probably the same for every
decorator, so Django can provide something more like:

###
from django.something import BaseViewDecorator
class LoginRequired(BaseViewDecorator):
    # magic to check for user credentials, in a CBV style
    ...

login_required = LoginRequired # backwards compatibility
###

With that, user code can look like:

class SomeProtectedView(LoginRequired, TemplateView):
    ... as usual...

@login_required()
def some_other_protected_view(request, arg1, arg2):
    ....as usual...

class NotAView():
    @login_required()
    def view_method(self, request, arg1, arg2):
       ... as usual ...

Which uses the "obvious" way of extension (decorators for functions/methods
and Mixins for classes) in each case (i.e., what Donald wants), but allows
implementing the decorator once, and not having to have specific wrappers
for each kind of view (universality, like Jacob wants).

This is a rough proposal to put another idea on the table, I know there's
the gotcha of the "login_required = LoginRequired" (which is to keep
backwards compatibility. Other alternative is rename the class to a non-PEP8
lowercase name). And I know there's the gotcha of having to use
login_required() instead of just login_required[1].

Does this sound like a good compromise between both positions?

Regards,
   Daniel

[1] I always found a bit irritating and antipythonic to have @login_required
as an alias for login_required() ; or in general, the behavior for
decorators with optional args, which besides needs to be coded explicitly
(DRY violation!) to behave like standard decorators. I know that changing
that would break a lot of code, and it's a story for another ticket, but I
couldn't miss the chance to complain :)

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