How to pass an optional argument to url in Django - django

I have an url pattern with one optional parameter:
# urls.py :
url(r'^(page/(?P<page>\w+))?$', MyIndexView.as_view(), name='index'),
Pagination and everything else works well, until I create an url to a specific page in my template:
# templates/mysite.html
{% url 'index' 54 %}
Then I get an error:
Reverse for 'index' with arguments '(54,)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'(page/(?P<page>\\w+))?$']
Without the parameter it works:
{% url 'index' %}
I also tried:
{% url 'index' page=54 %}
and got similar error.

You can create two URL patterns, one with a default parameter to 1 and the other with the page matching in the URL:
# urls.py :
url(r'^page$', MyIndexView.as_view(), {'page': 1}, name='index'),
url(r'^page/(?P<page>\w+)$', MyIndexView.as_view(), name='index'),
The third argument of the url function is kwargs, hence kwargs['page'] will be 1 in the first case and defined by the URL in the second.

Related

NoReverseMatch at /index

I am trying to understand why I am seeing a NoReverseMatch error when trying to use Django Contact Form.
The error occurs when I add a link using the following syntax to index.html:
<h3>Contact</h3>
If I use the following hardcoded syntax then no errors occur and the link to the contact form from index.html works as expected.
<h3>Contact</h3>
What I am trying to achieve is similar to what is shown the Django tutorial about removing hard coded urls.
The full error I see is:
NoReverseMatch at /index
Reverse for 'contact' with arguments '()' and keyword arguments '{}'
not found. 0 pattern(s) tried: []
In case of need, my abbreviated urls.py is:
urlpatterns = patterns('',
...
url(r'index$', views.index, name='index'),
...
url(r'^contact/', include('contact_form.urls')'),
)
I know I am missing something obvious!
It's because there is no url with name contact.
url(r'^contact/', include('contact_form.urls')'),
is url that will map all urls starting with contact to the contact_form.urls. Official docs don't say how to access contact view, but with basic understanding of django we can do something like this:
urlpatterns = patterns('',
...
url(r'index$', views.index, name='index'),
...
url(r'^contact/', include('contact_form.urls', namespace='contacts')),
)
and the in the template:
<h3>Contact</h3>
contact_form url name is found in the source code of the module.
when you use {% url 'contact' %} in template, the 'contact' is actually the name of route. In your url patterns there is no route with this name. You should include something like this into your contact_forms.urls.py:
url(r'$', views.index, name='contact_index')
Also, you should change "contact/" pattern to:
url(r'^contact/', include('contact_form.urls', namespace='contacts'))
and then use this when creating link in template:
{% url 'contacts:contact_index' %}

django template url tag optional parameter

Lets say I have these urlpatterns:
url(r'^area/(?P<area>[\w-]+)/?$', views.IndexView.as_view(), name="index"),
url(r'^$', views.IndexView.as_view(), name="index"),
How do I use template tag url to cope with the optional area parameter without if else
I tried the following:
{% url 'index' area=area %}
Problem is:
If area doesn't exist in template context, I get reverse not found.
If I set area to None, then url will become /area/None
Replace your index urls with just one index url.
url(r'^(?:area/(?P<area>[\w-]+))?$', views.IndexView.as_view(), name="index")
I can test that from shell
from django.core.urlresolvers import reverse, resolve
from django.template import Context, Template
Template("url1 is {% url 'index' %}").render(Context())
Template("url2 is {% url 'index' area=1 %}").render(Context())
Template("url3 is {% url 'index' area='ab-12-cd' %}").render(Context())
Output
u'url1 is /'
u'url2 is /area/1'
u'url3 is /area/ab-12-cd'

How can I get {% url logout %} to work in my Django template?

My Django app's site-wide urls.py file looks like this:
urlpatterns = patterns('',
url(r'^$', include('myApp.urls')),
url(r'^admin/', include(admin.site.urls)),
url (
r'^accounts/register/$',
RegistrationView.as_view(form_class=extendedRegistrationForm),
),
url(r'^accounts/', include('registration.backends.default.urls')),
url(r'^', include('myApp.urls')),
)
I also have a urls.py specific to myApp but I have not shown that here because I don't think it's relevant.
In my template file, I have this:
{% url logout %}
It gives me this error:
'url' requires a non-empty first argument. The syntax changed in Django 1.5, see the docs.
When I change the template to:
{% url 'logout' %}
It gives me the following error:
Reverse for 'logout' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
How do I put a link to logout in my view?
Add a logout url like this:
url(r"^logout/$", "django.contrib.auth.views.logout_then_login",
name="logout"),
The correct template syntax is:
{% url 'logout' %}
You didn't include django.contrib.auth's URLs in your urls.py, so there is no logout URL.
Try adding something like
url(r'^auth/', include('django.contrib.auth.urls')),
In django 3.0 {% url 'admin:logout' %} works perfect.

NoReverseMatch with Django-survey?

Ok, so this works in my urls.py:
url(r'^', survey_detail, {'survey_slug':'my-survey'}, name='survey-detail'),
I removed the above line and want to put the link in a template using {% url %}
I have the following line in urls.py:
url(r'^survey/', include('survey.urls'),
This is the line from the urls.py of the Survey app:
url(r'^detail/(?P<survey_slug>[-\w]+)/$', survey_detail, name='survey-detail'),
And this in my template:
{% url survey_detail 'my-survey' %}
I have also tried:
{% url survey_detail survey_slug='my-survey' %}
But I always get:
Reverse for 'survey_detail' with arguments '(u'my-survey',)' and keyword arguments '{}' not found.
or
Reverse for 'survey_detail' with arguments '()' and keyword arguments '{'survey_slug': u'my-survey'}' not found.
Any ideas?
The name is survey-detail and not survey_detail

NoReverseMatch Error

I keep getting this error for the django login system. Here is part of my urls.py:
(r'^contractManagement/login', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
The exact error I am getting:
Exception Type: NoReverseMatch
Exception Value: Reverse for ''django.contrib.auth.views.login'' with arguments '()' and keyword arguments '{}' not found.
I can't understand why i am getting this error. If you need anything else let me know.
You don't show where you are trying to reverse this URL, but it looks like you have double-quoted it. If you're using the url tag, note that you don't need quotes around the url name:
{% url django.contrib.auth.views.login %}
not
{% url 'django.contrib.auth.views.login' %}
You see that ''the.unknown.view'' is reported including too many qoutes.
It is because the quoted syntax will be valid in Django 1.5 and higher. For Django 1.3 or 1.4, you should activate the future behavior by this line in the template:
{% load url from future %}
which is valid also for Django 1.5.
Example for Django 1.5+
{% url "path.to.some.view" %}
Classic syntax for Django <= 1.4.x (without "future" command) is:
{% url path.to.some.view %}
I would give your url a name (in order to do that, you need to use the url method) Also you should add a trailing slash to all your urls, cause the django CommonMiddleware is going to be doing a 302 redirect on all your urls if you don't:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
url(r'^contractManagement/login/', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='contract_login'),
)
Then you can use reverse in your code, or url in your templates, and if you ever decide to change the actual url (ie: changedCotractManagement/login/), as long as the name is the same, your code will still be good.
in code:
from django.core.urlresolvers import reverse
reverse('contract_login')
in template:
{% url contract_login %}
Edit: per MrOodles