Migrating to class-based views and django.core.urlresolvers.reverse

636 views
Skip to first unread message

Daniel Swarbrick

unread,
Dec 7, 2010, 4:42:00 AM12/7/10
to Django developers
I have been tracking the development of class-based views for a few
weeks now, and am just starting to adapt some of my work-in-progress
sites. This post is in a bit of a grey area between django-users and
django-developers, but I'm curious what is suggested for sites that
make heavy use of django.core.urlresolvers.reverse() and {% url %} in
templates.

Obviously with the old function-based views, we could simply do this:

from django.core.urlresolvers import reverse

def my_view(request):
... do something useful ...
return response

my_view_url = reverse('my_app.views.my_view')

And likewise we could also reference that view using the {% url %} tag
in templates.

What is the recommendation for using reverse() and {% url %} when we
migrate to class-based views? So fat the only solution I have come up
with is naming the the URL patterns in urls.py, for example:

urlpatterns = patterns('',
(r'^$', TemplateView.as_view(template_name='main/index.html'), {},
'home'),
)

In the above case, we can now reverse('home') or {% url "home" %} -
but is this the only way? If so, one would have to give some careful
thought to the names of the URL patterns, so that it was readily
obvious what view each named URL actually was. For example, one might
end up using names like "myapp.IndexView" - a pseudo-hierarchical
naming scheme, to essentially bring us back to the place we were with
function-based view names.

I look forward to people's ideas about this...

bur...@gmail.com

unread,
Dec 7, 2010, 8:33:22 AM12/7/10
to django-d...@googlegroups.com
Hi Daniel,

I'm not core developer, but I think
http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces
should be used.

you can use reverse("yournamespace:someview"), and it's also cool to
do things like this in settings.py:

reverse_lazy = lazy(reverse, str)
LOGIN_REDIRECT_URL = reverse_lazy('yournamespace:your_main_page')

Perhaps it's not advertised as it should, and people continue to
invent their tricky namespace schemes...

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

--
Best regards, Yuri V. Baburov, Skype: yuri.baburov, MSN: bu...@live.com

Daniel Swarbrick

unread,
Dec 7, 2010, 12:08:49 PM12/7/10
to Django developers
Forgetting namespaces or existing named URL patterns for a moment, the
major difference is that with function-based views, we were giving a
qualified "module.function" parameter to reverse() or {% url %}.

How can we do that with class-based views, without naming every URL
pattern? Or is it not possible?

A side question that's been nagging at me during all this is, will
class-based views become the norm, even in places where we weren't
using function-based generic views? I was using direct_to_template()
in 99% of my views, simply because it was a shortcut for the whole
render_to_response('my_template.html', my_data_dictionary,
context_instance=RequestContext(request)) palaver. In most cases I was
still passing an extra_context, but it was a little bit less
typing ;-)

Another question (sorry - maybe these should be separate posts), how
does one go about using the permission_required() decorator with class-
based views, or something like the following:

@user_passes_test(lambda u: u.is_superuser)
def my_superview(request):
...
return response

Sorry if I'm jumping the gun a little bit. I realise this is a dev
version and is still in flux.

On Dec 7, 2:33 pm, "burc...@gmail.com" <burc...@gmail.com> wrote:
> Hi Daniel,
>
> I'm not core developer, but I thinkhttp://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-n...
> > For more options, visit this group athttp://groups.google.com/group/django-developers?hl=en.

Benjamin Wohlwend

unread,
Dec 7, 2010, 12:21:39 PM12/7/10
to django-d...@googlegroups.com
Hi Daniel

On Tue, Dec 7, 2010 at 6:08 PM, Daniel Swarbrick
<daniel.s...@gmail.com> wrote:
> Forgetting namespaces or existing named URL patterns for a moment, the
> major difference is that with function-based views, we were giving a
> qualified "module.function" parameter to reverse() or {% url %}.
>
> How can we do that with class-based views, without naming every URL
> pattern? Or is it not possible?

Simple. In your views.py:

my_view_function = MyViewClass.as_view()

You can then use `my_view_function` like every other view, like using
it in an url pattern without providing a name or decorating it.

But I think we are slowly approaching django-user territory here...

Kind regards,
Benjamin

Łukasz Rekucki

unread,
Dec 7, 2010, 12:36:40 PM12/7/10
to django-d...@googlegroups.com
On 7 December 2010 18:08, Daniel Swarbrick <daniel.s...@gmail.com> wrote:
> Forgetting namespaces or existing named URL patterns for a moment, the
> major difference is that with function-based views, we were giving a
> qualified "module.function" parameter to reverse() or {% url %}.
>
> How can we do that with class-based views, without naming every URL
> pattern? Or is it not possible?

A similar question was asked here:
http://groups.google.com/group/django-users/browse_frm/thread/847758c4f554c5b9/dee7ebf13296d1ec

It's not possible without extra work. But if you're already doing
extra work, you can just name the view and be nice to people who will
reuse your application. I currently use "<app>-<model>_<action>"
scheme in my projects.

>
> A side question that's been nagging at me during all this is, will
> class-based views become the norm, even in places where we weren't
> using function-based generic views? I was using direct_to_template()
> in 99% of my views, simply because it was a shortcut for the whole
> render_to_response('my_template.html', my_data_dictionary,
> context_instance=RequestContext(request)) palaver. In most cases I was
> still passing an extra_context, but it was a little bit less
> typing ;-)

Your anwser here is the code that was commited today:
http://code.djangoproject.com/changeset/14850
TemplateResponse replaces direct_to_template as a shortcut. CBVs
aren't meant to replace function-views entriely. They are mainly
targeted at generic views and reusable applications.

>
> Another question (sorry - maybe these should be separate posts), how
> does one go about using the permission_required() decorator with class-
> based views, or something like the following:
>
> @user_passes_test(lambda u: u.is_superuser)
> def my_superview(request):
>    ...
>    return response
>
> Sorry if I'm jumping the gun a little bit. I realise this is a dev
> version and is still in flux.

This is in the docs:
http://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating-class-based-views

PS. As Benjamin already mentioned, I think we're in django-users land now.

--
Łukasz Rekucki

Daniel Swarbrick

unread,
Dec 7, 2010, 2:10:27 PM12/7/10
to Django developers
That is indeed in the docs, and I have seen that. What eludes me is
how to use decorators more complex than login_required() from within
urls.py.

For example, this works fine:

from django.contrib.auth.decorators import user_passes_test
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, View

class IndexView(TemplateView):
template_name = 'index.html'

@method_decorator(user_passes_test(lambda u: u.is_superuser))
def dispatch(self, *args, **kwargs):
return super(IndexView, self).dispatch(*args, **kwargs)

But how would one avoid having to override the dispatch() method on
many classes, and put the user_passes_test() decorator in the urls.py
definition? Or for that matter, the permission_required() decorator?

As a side note, could a mixin be used to setup permission_required,
login_required etc, and user-defined class-based views be derived from
multiple parent classes?

Sorry if this has meandered into django-users land... maybe some
advanced CBV examples in the docs?

On Dec 7, 6:36 pm, Łukasz Rekucki <lreku...@gmail.com> wrote:
> On 7 December 2010 18:08, Daniel Swarbrick <daniel.swarbr...@gmail.com> wrote:
> > Another question (sorry - maybe these should be separate posts), how
> > does one go about using the permission_required() decorator with class-
> > based views, or something like the following:
>
> > @user_passes_test(lambda u: u.is_superuser)
> > def my_superview(request):
> >    ...
> >    return response
>
> This is in the docs:http://docs.djangoproject.com/en/dev/topics/class-based-views/#decora...

Sean Brant

unread,
Dec 7, 2010, 2:15:01 PM12/7/10
to django-d...@googlegroups.com, Django developers
Again this topic is now in django-user land.

I do this in views.py if want the decorator on all methods (get|post).

myview = login_required(MyView.as_view())

Reply all
Reply to author
Forward
0 new messages