0

I am having some weird issues with reverse lookups. Here is my url scheme.

url(r'^overview/', 'ledger.views.overview', name='overview'),
url(r'^overview/(?P<tutorial>\w+)$', 'ledger.views.overview', name='overview_tutorial'),

When I call return redirect('overview_tutorial', tutorial='tutorial') it isn't loading the tutorial version, it is loading the regular version, which is weird to me. I thought by specifying the name of the url it would use that url but instead it is matching on the first url. Adding a $ to the end of the url scheme solves the problem:

url(r'^overview/$', 'ledger.views.overview', name='overview'),
url(r'^overview/(?P<tutorial>\w+)$', 'ledger.views.overview', name='overview_tutorial'),

but I still don't understand why it is doing this. What I really want to do is have a url scheme like this:

url(r'^overview/', 'ledger.views.overview', name='overview'),
url(r'^overview/(?P<tutorial>\w+)$', 'ledger.views.overview', name='overview_tutorial'),
url(r'^overview/(?P<success>\w+)$', 'ledger.views.overview', name='overview_success'),
url(r'^overview/(?P<error>\w+)$', 'ledger.views.overview', name='overview_error')

and then I can redirect to the appropriate appropriate url name and pass in the different parameters. ie:

return redirect('overview_success', success='True')  #or
return redirect('overview_error', error='Login failed. Please try your username/password again')

but those both return as if I just called tutorial view. (which I am now realizing is because a reverse url lookup must build the url and then run it through the url patterns to see where it should direct to).

So then I tried doing this:

url(r'^overview/(?P<tutorial>\w+)$', 'ledger.views.overview', name='overview'),
url(r'^overview/(?P<tutorial>\w+)/(?P<success>\w+)$', 'ledger.views.overview', name='overview_success'),
url(r'^overview/(?P<tutorial>\w+)/(?P<success>\w+)/(?P<error>\w+)$', 'ledger.views.overview', name='overview_error'),

but when I call return redirect("overview_success", tutorial='', success="Hooray"), I again get an error:

Reverse for 'overview_success' with arguments '()' and keyword arguments '{'success': 'Hooray', 'tutorial': ''}' not found. 1 pattern(s) tried: ['overview/(?P<tutorial>\\w+)/(?P<success>\\w+)$']
Chase Roberts
  • 9,082
  • 13
  • 73
  • 131
  • What is the problem by adding the `$` anchor? – Reto Aebersold Oct 28 '14 at 17:26
  • I can add the '$' anchor, but if I specify a name, shouldn't it just jump right to that scheme? – Chase Roberts Oct 28 '14 at 17:29
  • 3
    The problem is that without the `$`anchor, your first rule matches always as all those URLs start with *overview/*. Therefore you need to mark teh end of teh string with the `$`anchor. – Reto Aebersold Oct 28 '14 at 17:34
  • The error you get on your edit is because there is no match... you tell it that the named group called `tutorial` should match `\w+` but you give it an empty string. You're also using named groups wrong, they shouldn't be used to send messages to the view, there is the messaging framework for that. Take a look at the documentation on how to use named groups: https://docs.djangoproject.com/en/1.7/topics/http/urls/#named-groups – Ngenator Oct 28 '14 at 17:42

1 Answers1

0

It looks like you are trying to use your urlconf to accept messages that you want to send to the user. For example your error message

return redirect('overview_error', error='Login failed. Please try your username/password again')

However that's not what named groups in the urlconf are for. They are for matching url patterns to determine which view to render. So when you are calling redirect it isn't just sending you to a new url, it's resolving that url based on what you pass it.

In your second example your redirect call

return redirect("overview_success", tutorial='', success="Hooray")

is trying to match against your url pattern

url(r'^overview/(?P<tutorial>\w+)/(?P<success>\w+)$', 'ledger.views.overview', name='overview_success'),

as something like overview//Hooray which as you can see is not a valid pattern because of the empty string passed to tutorial which expects 1 or more "word" characters.

You can use the messaging framework to send messages to the user. https://docs.djangoproject.com/en/1.7/ref/contrib/messages/#module-django.contrib.messages

Ngenator
  • 10,909
  • 4
  • 41
  • 46