new class based views

18 views
Skip to first unread message

Valentin Golev

unread,
Oct 19, 2010, 1:25:34 PM10/19/10
to Django developers
Hello,

I'm trying to use brand new Class Based Views and I have a question
about implementation.

Let's take a look at SingleObjectMixin.get_object():
http://code.djangoproject.com/browser/django/trunk/django/views/generic/detail.py

Why does it use function arguments, and not self.kwargs, while, for
example, View.get() or post() methods use instance variables?

Is it going to change? I'm just curious. I understand that since this
is not the release, API is subject to change, so I'd like to know is
it going to change and how.

Thank you,
Valya

Russell Keith-Magee

unread,
Oct 19, 2010, 8:36:50 PM10/19/10
to django-d...@googlegroups.com

Good catch! I've just made a change (r14292) to make get_object() more
consistent with the rest of the class-based view API, dropping the
(pk=None, slug=None, **kwargs) arguments in favor of using
self.kwargs. I've also added formal API documentation for
get_object(), which was omitted for some reason.

Thanks for the feedback!

Yours,
Russ Magee %-)

Valentin Golev

unread,
Oct 20, 2010, 6:01:55 AM10/20/10
to django-d...@googlegroups.com
Awesome, thank you!

I've asked about @login_required and class based views in
django-users, and I'd like to ask here: are something like
LoginRequiredMixin's planned?

--
Best Regards,
Valentin Golev
Lead Developer
r00, http://r00.ru

http://valyagolev.net
+7 921 789 0895, avaiable 12:00-18:00 MSK

> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to django-develop...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
>
>

Russell Keith-Magee

unread,
Oct 20, 2010, 6:59:46 AM10/20/10
to django-d...@googlegroups.com
On Wed, Oct 20, 2010 at 6:01 PM, Valentin Golev <m...@valyagolev.net> wrote:
> Awesome, thank you!
>
> I've asked about @login_required and class based views in
> django-users, and I'd like to ask here: are something like
> LoginRequiredMixin's planned?

No, nothing like that is planned. This is a situation were decorators
will be a better match in the general case, because login redirection
can usually be transparently wrapped around a view.

You should be able to use decorators on class based views in the same
way that you use them on normal function views.

Yours,
Russ Magee %-)

Valentin Golev

unread,
Oct 20, 2010, 7:05:47 AM10/20/10
to django-d...@googlegroups.com
As far as I know, I can just say:

@login_required
class MyView(View):
# ...

since it will wrap __init__

I need either to create a decorator for decorators:
@on_dispatch(login_required)
class MyView(View):

or decorate result of MyView().as_view().

Maybe I'm wrong. I think it will be great to add something about it to
docs, since decorators is extremely wide-used feature.

--
Best Regards,
Valentin Golev
Lead Developer
r00, http://r00.ru

http://valyagolev.net
+7 921 789 0895, avaiable 12:00-18:00 MSK

Valentin Golev

unread,
Oct 20, 2010, 7:07:30 AM10/20/10
to django-d...@googlegroups.com
Almost everything I'm talking about right now is from this thread:

http://groups.google.com/group/django-users/browse_frm/thread/5239e284b5c285d5/a2676f257d37cf85#a2676f257d37cf85

("login_required and new class based views" in django-users in case
the link doesnt work.)

--
Best Regards,
Valentin Golev
Lead Developer
r00, http://r00.ru

http://valyagolev.net
+7 921 789 0895, avaiable 12:00-18:00 MSK

Russell Keith-Magee

unread,
Oct 20, 2010, 7:25:57 AM10/20/10
to django-d...@googlegroups.com
On Wed, Oct 20, 2010 at 7:05 PM, Valentin Golev <m...@valyagolev.net> wrote:
> As far as I know, I can just say:
>
> @login_required
> class MyView(View):
>   # ...
>
> since it will wrap __init__
>
> I need either to create a decorator for decorators:
> @on_dispatch(login_required)
> class MyView(View):
>
> or decorate result of MyView().as_view().
>
> Maybe I'm wrong. I think it will be great to add something about it to
> docs, since decorators is extremely wide-used feature.

As I've commented on the django-users thread, Django already provides
method_decorator(), which provides a way to decorate the dispatch
function (or any individual get/post etc HTTP method) on a class-based
view.

The other simple way to decorate a view is to decorate the result of
the as_view() call in the URL pattern -- i.e., instead of deploying:

MyView.as_view()

deploy:

login_required(MyView.as_view())

A class decorator (and/or a wrapper function for turning decorators
into class decorators) is also an interesting idea. However, unlike
method_decorator(), a class_decorator() would need to be
view-specific, since it needs to modify the class it wraps in a
specific way, rather than the completely generic approach that
method_decorator() can take.

Regardless, your point about documenting these approaches is well
taken. It isn't immediately obvious how decoration should work in a
class-based world. If you open a ticket for this, that will help make
sure that this idea isn't forgotten.

Yours,
Russ Magee %-)

Valentin Golev

unread,
Oct 20, 2010, 7:41:15 AM10/20/10
to django-d...@googlegroups.com
I think class decorator for views only is a great idea, because it will be:

a) just like with old view functions decorators
b) does not require any method overrides/imports into urls.py/explicit
transformations in views.py

I'd like Django to have a decorator for turning old decorators into
decorators for class based views. I've hardly seen @login_required and
lots of other common decorators not used in the view context, so why
avoid being attached to Django views interface, since we already made
up our minds about having such an interface.

So I think, both tickets - for docs and for "@on_dispatch()"
decorators - are worth it.

--
Best Regards,
Valentin Golev
Lead Developer
r00, http://r00.ru

http://valyagolev.net
+7 921 789 0895, avaiable 12:00-18:00 MSK

Luke Plant

unread,
Oct 20, 2010, 9:59:44 AM10/20/10
to django-d...@googlegroups.com
On Wed, 2010-10-20 at 19:25 +0800, Russell Keith-Magee wrote:

> A class decorator (and/or a wrapper function for turning decorators
> into class decorators) is also an interesting idea.

An argument against this is "one way to do it". If I look at a class
and want to know what decorators are applied, if would be nice if there
was only one place to look. I guess that that one place could be the
class rather than the 'dispatch' method, if we encourage that practice,
but that pattern might be hard to encourage since class-decoration is
less obvious (and certainly much less well established in the Django
code base) than method decoration.

Luke

--
If you can't answer a man's arguments, all is not lost; you can
still call him vile names. (Elbert Hubbard)

Luke Plant || http://lukeplant.me.uk/

Łukasz Rekucki

unread,
Oct 20, 2010, 10:05:27 AM10/20/10
to django-d...@googlegroups.com
On 20 October 2010 15:59, Luke Plant <L.Pla...@cantab.net> wrote:
> On Wed, 2010-10-20 at 19:25 +0800, Russell Keith-Magee wrote:
>
>> A class decorator (and/or a wrapper function for turning decorators
>> into class decorators) is also an interesting idea.
>
> An argument against this is "one way to do it".  If I look at a class
> and want to know what decorators are applied, if would be nice if there
> was only one place to look.  I guess that that one place could be the
> class rather than the 'dispatch' method, if we encourage that practice,
> but that pattern might be hard to encourage since class-decoration is
> less obvious (and certainly much less well established in the Django
> code base) than method decoration.

OTOH, it'a annoying to have to write an dispatch() method with a super
inside (which effectively does nothing), just to apply a decorator.

--
Łukasz Rekucki

Valentin Golev

unread,
Oct 20, 2010, 10:08:37 AM10/20/10
to django-d...@googlegroups.com
Well, since we are already using class Mixins for extending View
functionality, we can try to turn decorators into mixins. Having two
ways to add some functionality to class (decorators and mixins) can be
somewhat uncomfortable.

I had some doubts if mixins can act as a "wrappers" to defined
functions, but, as I was told, these doubts were based on my poor
understanding of how "super()" and mixins work.

I totally agree with Łukasz about annoyance of decorating a dispatch() function.

--
Best Regards,
Valentin Golev
Lead Developer
r00, http://r00.ru

http://valyagolev.net
+7 921 789 0895, avaiable 12:00-18:00 MSK

Russell Keith-Magee

unread,
Oct 20, 2010, 10:13:00 AM10/20/10
to django-d...@googlegroups.com
On Wed, Oct 20, 2010 at 9:59 PM, Luke Plant <L.Pla...@cantab.net> wrote:
> On Wed, 2010-10-20 at 19:25 +0800, Russell Keith-Magee wrote:
>
>> A class decorator (and/or a wrapper function for turning decorators
>> into class decorators) is also an interesting idea.
>
> An argument against this is "one way to do it".  If I look at a class
> and want to know what decorators are applied, if would be nice if there
> was only one place to look.  I guess that that one place could be the
> class rather than the 'dispatch' method, if we encourage that practice,
> but that pattern might be hard to encourage since class-decoration is
> less obvious (and certainly much less well established in the Django
> code base) than method decoration.

I'm not sure that argument holds up. Right now, we already have 2 ways
to do it - you can decorate the view function at time of definition,
and you can decorate when it is included in the URL pattern.

The class-based view case is also complicated by the common usage
pattern. Consider a prototypical view:

class MyView(View):
def get(self, request, *args, **kwargs):
...
def post(self, request, *args, **kwargs):
...

You don't have to define dispatch or as_view -- the two places that
can be decorated to provide class-wide behavior. You could decorate
both get *and* post -- which may be a good approach in some cases (say
you want all GETs to be allowed, but POSTs to be login protected) --
but it's an unusual duplication to require for the common case. You
could also decorate the MyView.as_view() line in the URL pattern, but
that doesn't enforce the decorator for every use.

There's no simple direct analog of the "make sure every access to this
view is decorated". To me, a class-view-decorator seems like a way to
express the existing use case.

Yours,
Russ Magee %-)

Łukasz Rekucki

unread,
Oct 20, 2010, 12:13:01 PM10/20/10
to django-d...@googlegroups.com
Created a ticket for this: http://code.djangoproject.com/ticket/14512

> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to django-develop...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
>
>

--
Łukasz Rekucki

Luke Plant

unread,
Oct 20, 2010, 1:42:24 PM10/20/10
to django-d...@googlegroups.com
On Wed, 2010-10-20 at 16:05 +0200, Łukasz Rekucki wrote:

> OTOH, it's annoying to have to write an dispatch() method with a super


> inside (which effectively does nothing), just to apply a decorator.

That's a good point I hadn't thought of, as are Russell's other points.

Just to put it on the table, another option we thought of at one point
was to have a 'decorators' attribute on the class, which is a list of
decorators that is applied by the as_view() method. It would in theory
allow you to add decorators to either end of the set of decorators that
are applied, something like this:

class MyView(SomeOtherView):

decorators = SomeOtherView.decorators + [my_dec_1, my_dec_2]

It gets a bit trickier with multiple inheritance. I don't know if that
would be too much of a big deal - I would imagine that most of the mixin
classes would not be providing decorators. But then my imagination is
probably limited.

Russell Keith-Magee

unread,
Oct 20, 2010, 8:23:28 PM10/20/10
to django-d...@googlegroups.com
On Thu, Oct 21, 2010 at 1:42 AM, Luke Plant <L.Pla...@cantab.net> wrote:
> On Wed, 2010-10-20 at 16:05 +0200, Łukasz Rekucki wrote:
>
>> OTOH, it's annoying to have to write an dispatch() method with a super
>> inside (which effectively does nothing), just to apply a decorator.
>
> That's a good point I hadn't thought of, as are Russell's other points.
>
> Just to put it on the table, another option we thought of at one point
> was to have a 'decorators' attribute on the class, which is a list of
> decorators that is applied by the as_view() method.  It would in theory
> allow you to add decorators to either end of the set of decorators that
> are applied, something like this:
>
> class MyView(SomeOtherView):
>
>    decorators = SomeOtherView.decorators + [my_dec_1, my_dec_2]
>
> It gets a bit trickier with multiple inheritance.  I don't know if that
> would be too much of a big deal - I would imagine that most of the mixin
> classes would not be providing decorators.  But then my imagination is
> probably limited.

Meh - this seems like reinventing a syntactic wheel to me. Python 2.6
has class decorators. They work in a predictable way, with predictable
MRO combination rules. Trying to invent a new class-attribute syntax
for class decoration seems like asking for trouble.

Yours,
Russ Magee %-)

Reply all
Reply to author
Forward
0 new messages