views:

131

answers:

3

I've found very odd thing about using reverse in Django 1.2.1.

I have:

myapp/
   views.py
   urls.py

in urls.py

from django.conf.urls.defaults import *
urlpatterns = patterns('myapp.views',
 url(r'^$', 'browse'),
)

in views.py

from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse

print reverse('myapp.views.browse')     # <----- this will print correct value  

def browse (request):
    print reverse('myapp.views.browse') # <----- this fails with exception
    return render_to_response('myapp/browse.html')

When I put reverse method anywhere outside the view method (browse - in this case) I get an exception in every further use of reverse or {% url %} tag.

NoReverseMatch at /
Reverse for 'myapp.views.browse' with arguments '()' 
and keyword arguments '{}' not found.

WTF? When I comment/delete the print line outside browse() , second print line inside browse() magically start working!


The most basic case is:

class MyForm(forms.Form):
   field = forms.CharField(default=reverse(....))

def some_view(request):
   print reverse(...)
   ....

1) I define a class in main-scope that is initialized when django initialize (and runs reverse) 2) When a request comes the some_view function has been triggered and it evaluates the reverse function again (and fails with exception).

I don't see anything bad at all in this approach. Why not to initialise some values in the django main-scope with results of the reverse() function ?

A: 

I agree that this is very strange behavior.

Can you explain why you need to call the reverse function outside of your view like that?

Matthew J Morrison
+1  A: 

First, you should be naming your URLs in order to use reverse. That is the correct approach AFAIK.

Second, why are you calling reverse from within a FormField? I really don't get it.

Maybe you could enlighten us by posting the full code rather than a curated set of snippets.

# urls.py

url(r'^/$', 'home_view', name='home'),
url(r'^login/$', 'login_view', name='login'),


# views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect

def login_view(request):
    # do login stuff and redirect to home
    return HttpResponseRedirect(reverse('home'))

def home(request):
    # do home stuff

    return render_to_response("home.html", locals(), context_instance=RequestContext(request))
airstrike
+1  A: 

You will probably need to pass 'request' as the second parameter when calling reverse() from within the view function after it's already been called.

def browse(request):
    print reverse('myapp.views.browse', args=[request])

This is odd behavior indeed, but this might possibly be a solution for now.

Scott