Django - use redirect view with multiple parameters - django

Im trying to redirect to a view with multiple parameters:
in my urls.py (app exhibition) I have:
path('map/<float:lat>/<float:lng>/<int:zoom>', views.MapView.as_view(), name='map')
where float is defined in a path converter like this:
'[-+]?\d*\.?\d*'
For the redirection I have:
return redirect('exhibition:map', lat=48.128365,long=11.5662713,zoom=3)
After hours of trying and researching similar questions I still get:
Reverse for 'map' with keyword arguments '{'lat': 48.128365, 'long': 11.5662713, 'zoom': 3}' not found. 1 pattern(s) tried: ['de/map\\/(?P<lat>[-+]?\\d*\\.?\\d*)\\/(?P<lng>[-+]?\\d*\\.?\\d*)\\/(?P<zoom>[0-9]+)$']
If I adjust the url pattern and the redirect call to a single pattern (be it float or int) the redirection works. Thus the problem should be related to my usage of multiple parameters - but I just can see what is wrong.
Any hints welcome!

i guess it's typo, you have defined lng as second parameter in your path but in redirect statement you call it long, it should be
return redirect('exhibition:map', lat=48.128365, lng=11.5662713, zoom=3)

Related

what is the difference between reverse, reverse_lazy, resolve and redirect? [Django]

what is the difference between those next terms:
reverse, reverse_lazy, resolve and redirect
I think when I have to use return then I have to use redirect but if this is true?; why I can't use reverse instead of redirect?
also, when I should use these methods?
resolve() function can be used for resolving URL paths to the corresponding view functions.
reverse() function: It’s similar to the url template tag which use to convert namespaced url to real url pattern.
For example:
def test_list_reverse():
"""cheeses:list should reverse to /cheeses/."""
assert reverse('cheeses:list') == '/cheeses/'
def test_list_resolve():
"""/cheeses/ should resolve to cheeses:list."""
assert resolve('/cheeses/').view_name == 'cheeses:list'
• Reversing the view name should give us the absolute URL.
• Resolving the absolute URL should give us the view name.
The example in resolve gives a good idea of what's it for. Generally I've only used reverse as I need the url. I haven't used it but resolve gives you the view that the reverse url points to
For more details read this article

Django: Multiple parameters in URLs reverse resolution without querystrings or captured parameters

Without using query strings (like ?case=/2/), nor captured parameters in the url conf (like ?P) (so they dont show up in the url),
is there a way to pass parameters to a view function when using URLs reverse resolution?
Hopefully an example will clarify my question:
With captured parameters I could do:
views.py
...
return HttpResponseRedirect(reverse('videos:show_details', args=[video.id]))
urls.py
...
url(r'^club/(?P\d+)/$',views.details, name='show_details'),
...
But what if the view details needs / accepts more parameters, for example:
def details (request, video_id, director='', show_all=True):
And we dont want them to show up in the url?
Any way of using args or kwargs without them being in the url?
Im sure Im missing something trivial here :S
Hopefully someone can point me in the right direction.
Thanks!
I'm not sure this is what you mean, but you can pass extra arguments to the url pattern. This allows multiple urls that point to the same view to use different arguments:
url(r'^club/(?P<pk>\d+)/$', views.details, kwargs={'show_all': False}, name='show_details')

Django url patterns having reverse lookup issues with optional parameters

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+)$']
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

django template throws NoReverseMatch error

I had two methods create and update in the views, in which update takes one argument whereas create does not take any. I have decided to turn them into only one function update_create because they were not that different.
This is how the new method in views looks:
def update_create(request, id=None):
This is my urls.py:
url(r'^(\d+)/update/$|create/$', update_create, name='update_create'),
This is how my template looks in templates/list.html
Create a new event
I got this error when using the above code:
NoReverseMatch at /agenda/list/
Reverse for 'update_create' with arguments '()' and keyword arguments '{}' not found.
But, if I use this in my templates instead (I have added an argument), it works without any errors:
Create a new event
Can someone explain what's happening? Why previous code didn't work, and Why the new code is working?
URL pattern (\d+) expects number to be provided as argument. To resolve the issue simply provide urls like this:
url(r'^(\d+)/update/$', update_create, name='update_create'),
url(r'^update/$', update_create, name='update_create'),
As mariodev pointed out, your url pattern was expecting a digit in front of the url. As such, your first url:
Create a new event
would generate a url like /update, which wasn't a valid url. However, the latter url:
Create a new event
would generate a url like /1/update, which was a valid url.
From the django docs: https://docs.djangoproject.com/en/dev/topics/http/urls/
Basically subsequent arguments get parsed on first come first serve, and passed to your view. Another thing to consider when developing is using explicitly named parameters, as the django docs elaborate on.

Django: Permanent redirect of URL with regex parameters

I've been looking all over and can't find what I'm looking for.
I've found a way to redirect urls without parameters and keywords - but how to do it with parameters?
I want to redirect this:
(r'^andelsboligforeninger/(?P<page>[\d]*?)/$', 'cooperatives'),
to this:
(r'^liste-over-andelsboligforeninger/(?P<page>[\d]*?)/$', 'cooperatives'),
It should be a permanent redirect. This will be good for the SEO, and I get so many debug mails because of googlebot.
It seems I've found my answer in the django docs - I didn't look hard enought after all!
https://docs.djangoproject.com/en/1.1/ref/generic-views/
urlpatterns = patterns('django.views.generic.simple',
('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
)
First of all you need to do some changes in the url. Use url function and then give a name to the url. You have some issues in your url, for example you have used ?P but did'nt give a name to the capturing group. Second [\d]*? there is no need for ? because * means there can be a digit or not at all. So after considering all the above mentioned bugs and techniques in the end your url should look like this:
url(r'^liste-over-andelsboligforeninger/(?P<cooperative_id>\d*)/$', 'cooperatives', name="cooperatives")
Then in the view you can use reverse url resolution as:
redirect(reverse('cooperatives', kwargs={'cooperative_id': some_id}))