Opened 13 years ago

Closed 11 years ago

#11712 closed Bug (fixed)

First use of reverse() freezes its cache

Reported by: beuc@… Owned by: nobody
Component: Core (Other) Version: 1.1
Severity: Normal Keywords: urlresolvers, reverse
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: yes
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


I'm using a reverse() for a 'post_save_redirect' parameter, that refers to a view declare above.

This doesn't work if said view is declared in the same patterns block, so I'm using several patterns blocks.

However, and that's the main issue, all view declared later in the code are ignored. Example:

from django.conf.urls.defaults import *
from django.core.urlresolvers import reverse, clear_url_caches
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.models import User, Group

urlpatterns = patterns('',
      { 'queryset': User.objects.all(), },

urlpatterns += patterns('',
      { 'form_class': UserChangeForm,
        'post_save_redirect': reverse('user_list'), },

urlpatterns += patterns('',
      { 'queryset': Group.objects.all(), },

test = reverse('group_list')

=> Reverse for 'group_list' with arguments '()' and keyword arguments '{}' not found.

The important part is:

'post_save_redirect': reverse('user_list'),

change it to:

'post_save_redirect': 'whatever',

and everything works fine.

This sounds like a cache issue, but interestingly calling clear_url_caches() before the last line doesn't help.

In 1.0.2 this is a one-time error that disappears on the next reload so it's not very important.

On 1.1, this is a permanent error which is very confusing and long to track: the view's reverse name is properly defined, but still Reverse says it cannot find it.

I'm not sure I understand all the aspects of this issue, but to the least, its error reporting needs to be improved.

Change History (7)

comment:1 Changed 13 years ago by dc

Resolution: wontfix
Status: newclosed

You cannot call reverse before URLconf module is completely initialized.

comment:2 Changed 13 years ago by Beuc

Resolution: wontfix
Status: closedreopened


Thanks for the quick reply.

Sorry for reopening, but I think there's a misunderstanding.

  • I pointed a legitimate (DRY) use case that needs a solution, which is using reverse urls for the post_save_redirect (and post_delete_redirect) field in generic views. Using lazy(reverse) raises an exception when it's proxy is called, incidentally.


comment:3 Changed 13 years ago by Russell Keith-Magee

Triage Stage: UnreviewedAccepted

You should be able to use a reverse() as an argument to post_save_redirect et al. I'm not sure what the right solution is here (making reverse lazy? fixing reverse so it can be called lazy?), but we should fix this and document the fix.

comment:4 Changed 12 years ago by Mandx

Needs documentation: set

Also, seems logical to use

class HomeFeed(Feed)
    # ...
    link = reverse('home_url')
    # ...

But, since the feed is an instance created during URLConf init, reverse() won't work. Instead, a link() method must be used, so reverse() is called at feed generation, not when the feed instance is created, like this:

class HomeFeed(Feed)
    # ...
    def link(self):
        return reverse('home_url')
    # ...

I've file another ticket (#13501) that is a duplicated of this one, because, as Beuc says, this should be well documented, since no errors are thrown. It took me 2 days to figure out the problem.

comment:5 Changed 12 years ago by Benoît Bryon

See #5925 about lazy reverse().

In URLconf, view decorators, settings, or anywhere parsed before URL resolver is initialized, a lazy version of reverse() can help.

comment:6 Changed 12 years ago by Julien Phalip

Severity: Normal
Type: Bug

comment:7 Changed 11 years ago by Julien Phalip

Easy pickings: unset
Resolution: fixed
Status: reopenedclosed

This use case can now be properly addressed since the introduction of reverse_lazy in [16121]. This is also documented here:

Note: See TracTickets for help on using tickets.
Back to Top