Code

Opened 5 years ago

Closed 3 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:

Description

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('',
  url(r'^user/$',
      'django.views.generic.list_detail.object_list',
      { 'queryset': User.objects.all(), },
      name='user_list'),
)

urlpatterns += patterns('',
  url(r'^user/(?P<object_id>[a-zA-Z0-9_]+)/$',
      'django.views.generic.create_update.update_object',
      { 'form_class': UserChangeForm,
        'post_save_redirect': reverse('user_list'), },
      'utilisateur_detail'),
)

urlpatterns += patterns('',
  url(r'^group/$',
      'django.views.generic.list_detail.object_list',
      { 'queryset': Group.objects.all(), },
      name='group_list'),
)

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.

Attachments (0)

Change History (7)

comment:1 Changed 5 years ago by dc

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

You cannot call reverse before URLconf module is completely initialized.

comment:2 Changed 5 years ago by Beuc

  • Resolution wontfix deleted
  • Status changed from closed to reopened

Hi,

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.

Regards.

comment:3 Changed 4 years ago by russellm

  • Triage Stage changed from Unreviewed to Accepted

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 4 years ago by gmandx

  • 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 4 years ago by benoitbryon

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 3 years ago by julien

  • Severity set to Normal
  • Type set to Bug

comment:7 Changed 3 years ago by julien

  • Easy pickings unset
  • Resolution set to fixed
  • Status changed from reopened to closed

This use case can now be properly addressed since the introduction of reverse_lazy in [16121]. This is also documented here: http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.