Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a reverse URL for a generic view?

Tags:

django

reverse

Here is the question how do I use reverse for the generic view object_detail?

If I use it like the following, the error message will be: NoReverseMatch at /comment/add/ Reverse for '' with arguments '()' and keyword arguments '{}' not found.

in views.py:

urlresolvers.reverse('django.views.generic.list_detail.object_detail')
              return HttpResponseRedirect(resp)

in urls.py

common_info_dict = {
    'extra_context':{
         'blogtitle':"Thinking",
         'blogsubtitle':"- blog system",
         'articles_count':Entry.objects.count,
         'comments_count': 0,
         'visitors_count' : 0,
         'category_list':Category.objects.all,
         'tag_list':Tag.objects.all,
         'comment_form': CommentForm,
    },
}

object_detail_info_dict = {
    'queryset': Entry.objects.all(),
    'slug_field': 'slug',
    'template_object_name': 'post',
}

object_detail_info_dict.update(common_info_dict)

    urlpatterns += patterns('django.views.generic.list_detail',
       (r'^posts/(?P<slug>[-\w]+)/$', 'object_detail', object_detail_info_dict),
    )
like image 442
Jacky Avatar asked Apr 03 '09 07:04

Jacky


2 Answers

The only way to use reverse with generic views - named urls config.

urlpatterns += patterns('django.views.generic.list_detail',
  (r'^posts/(?P<slug>[-\w]+)/$', 'object_detail',
                          object_detail_info_dict, 'post_detail'),
)

reverse('post_detail', args=('foobar',))
like image 146
Alex Koshelev Avatar answered Nov 15 '22 22:11

Alex Koshelev


This question seems to be for older versions of Django. I'm not familiar with how the old generic views work. But the new class-based generic views have the same problem.

Reversing doesn't work "out of the box" because View.as_view() returns a different wrapper function each time, and they don't compare equal to each other, so reverse() can't find the reverse route by comparing two functions that aren't equal.

There is another way, although it's non-standard. This is what I do for my class-based views:

class OrderView(LoginRequiredMixin, CreateView):
    model = Order
    form_class = OrderForm

OrderView.plain_view = staticmethod(OrderView.as_view())

In this case, I use plain_view to mean the view returned by as_view() with no arguments. If you pass arguments to as_view(), then the wrapper it returns will actually be different to the plain one. So if you need both, you'd have to assign them to different properties:

OrderView.plain_view = staticmethod(OrderView.as_view())
OrderView.bonk_view = staticmethod(OrderView.as_view(whee='bonk'))

You can link to these view attributes in urls.py:

urlpatterns = patterns('',
    url(r'^order/$', views.OrderView.plain_view),
    url(r'^frob/$', views.OrderView.bonk_view),

and then you can reverse them by reversing the view attributes:

def get_success_url(self):
    return reverse(OrderView.plain_view)

def get_failure_url(self):
    return reverse(OrderView.bonk_view)
like image 39
qris Avatar answered Nov 15 '22 20:11

qris