Django

Code

Ticket #5925 (new)

Opened 2 years ago

Last modified 2 months ago

Unable to use urlresolvers (url,reverse ) feature in redirect argument of decorator user_passes_test

Reported by: anonymous Assigned to: nobody
Milestone: Component: Core framework
Version: SVN Keywords: urlresolver,reverse,decorator,url,permalink
Cc: yann.malet@gmail.com, hv@tbz-pariv.de Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

trying something like :

@user_passes_test(lambda u: my_function(u),login_url = reverse('my_reverse_key'))
def my view(request)
   pass
   ...

yields an error when importing "urls.py" (i.e.really quickly)

Attachments

Change History

11/26/07 04:09:15 changed by yml

  • cc set to yann.malet@gmail.com.
  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

One other side effect of the issue describes above is that it breaks the url resolution for reverse, {%url%}, permalink and company. I have the case in one of my application where some views are protected by : """ @user_passes_test(lambda u: Group.objects.get(name='admin') in u.groups.all(), login_url=reverse("auth_login")) """ This lead to some nasty bugs in the url resolution of an other view.

I hope this description will help.

11/26/07 06:40:27 changed by anonymous

  • keywords changed from reverse,decorator to reverse,decorator,url,permalink.

11/30/07 09:22:46 changed by anonymous

  • keywords changed from reverse,decorator,url,permalink to urlresolver,reverse,decorator,url,permalink.
  • summary changed from Unable to use url reverse feature in redirect argument of decorator user_passes_test to Unable to use urlresolvers (url,reverse ) feature in redirect argument of decorator user_passes_test.

12/08/07 12:44:10 changed by Eratosfen

It looks like problem concerns not only user_passes_test. reverse() can't be used at all decorators of views. Since the decorators of your views are evaluated during parsing urls.py you have an 'chicken - egg' problem. The method reverse() can't be used since urls.py is not read.

The solution, I see, is to evaluate the reverse() lazy.

12/09/07 09:18:34 changed by yml

I do not know if this information can help. I have observed that @cache (decorator) does not trigger any error message.

01/02/08 08:35:47 changed by Thomas Güttler <hv@tbz-pariv.de>

  • cc changed from yann.malet@gmail.com to yann.malet@gmail.com, hv@tbz-pariv.de.
  • stage changed from Unreviewed to Accepted.

I have this problem, too.

Here is my solution:

# file lazy.py
from django.core import urlresolvers

class lazy_string(object):
    def __init__(self, function, *args, **kwargs):
        self.function=function
        self.args=args
        self.kwargs=kwargs
        
    def __str__(self):
        if not hasattr(self, 'str'):
            self.str=self.function(*self.args, **self.kwargs)
        return self.str

def reverse(*args, **kwargs):
    return lazy_string(urlresolvers.reverse, *args, **kwargs)

Just use

from lazy import reverse

instead of

from django.core.urlresovlers import reverse

09/09/08 13:47:56 changed by mtredinnick

Should be possible to solve this using our existing django.utils.functional.lazy() function to create lazy_reverse. Reinventing that wheel is something to avoid. reverse() is a function that returns a unicode object (we should ensure that it does return unicode and not str). So there are a few things to do here: auditing existing reverse, hooking up reverse_lazy, documentation, tests, etc, but that sounds like a plan. At least in my head.

09/10/08 03:08:18 changed by guettli

I think it is better to alter reverse() than to invent a new method lazy_reverse(). The recursive import error results in very strange Exceptions: Modules are missing methods/attributes that are in the source code. It took me some time to find out what's wrong, although I am using Python since seven years.

05/06/09 11:12:31 changed by akaihola

This urls.py works as expected (redirects from / to /comehere/), so django.utils.functional.lazy() seems to work as mtredinnick suggested:

from django.conf.urls.defaults import *
from django.core.urlresolvers import reverse
from django.utils.functional import lazy
from django.http import HttpResponse

reverse_lazy = lazy(reverse, unicode)

urlpatterns = patterns('',
    url(r'^comehere/', lambda request: HttpResponse('Welcome!'), name='comehere'),
    url(r'^$', 'django.views.generic.simple.redirect_to',
        {'url': reverse_lazy('comehere')}, name='root')
)

05/08/09 11:07:36 changed by thejaswi_puthraya

  • component changed from Uncategorized to Core framework.

Add/Change #5925 (Unable to use urlresolvers (url,reverse ) feature in redirect argument of decorator user_passes_test)




Change Properties
Action