Django - reverse not found for included URL pattern - django

I've got the following in an old Django 1.8 (sorry...) site:
url(r"^racing/(?P<type>(dog|horse|pigeon))/", include("racing.urls")),
which pulls in the racing URLs:
urlpatterns = patterns("racing.views",
url(r"^(?P<season>\d+)/$", "season_view", name="season_home"),
}
The view function defines a default for the type argument:
def season_view(request, season, type="horse")
Which, to my mind, means I should be able to (in a template) do:
{% url "season_home" season=nav.season.year %}
But it's throwing an error:
Reverse for 'season_home' with arguments '()' and keyword arguments '{u'season': 2019L}' not found. 1 pattern(s) tried: [u'racing/(?P<type>[-\\w]+)/(?P<season>\\d+)/$']
What am I missing?

Your url pattern need 2 variables to be passed: type and season:
So you are passing only season and nothing for type.
Try to add type like:
{% url "season_home" type=my_type season=nav.season.year %}
where my_type is your type variable.

I can see that you are using default parameters in your views. So, you are expecting that if you are not passing a type parameter through your template, the type is set to horse as default.
Everything is okay but in your main url patterns, you need to be able to match the rules where no parameter is passed. You can try something like:
url(r"^/", include("racing.urls")),
url(r"^racing/(?P<type>(dog|horse|pigeon))/", include("racing.urls")),
This configuration helps you to capture both the cases when you supply a type parameter or not.

Related

Create Django named URL using template variable?

How do you specify a named URL pattern in Django if you need to pass it a template variable? My template contains the following URL:
# templates/welcome.html
# Link to template that shows all members near member with this uid
Show members near you
My top-level URLconf file contains the following pattern which points
to the application-specific url file:
# conf/urls.py
urlpatterns = patterns('',
...
url(r'^members/', include('apps.members.urls')),
...
)
Here is my application-specific url file:
# app/members/url.py
url(r'^near/(?P<uid>\d{1,})/$',
'show_members',
{'template': 'show_members.html'},
name='show-members-near'),
This is the error I get:
NoReverseMatch at /personal_profile/welcome/
Reverse for 'show-members-near' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['members/near/(?P<uid>\\d{1})/$']
I tried to insert a keyword argument like this but it didn't work:
Show members near you
After doing some research, everything I read seemed to indicate that the keyword argument should be passed the way I did it up above. What I'm trying to do is the equivalent of the following which does work:
See who's here
How do I specify a keyword argument? I didn't see anything that addresses this situation in the Django docs (although I might have missed it).
Thanks!
You'd just pass the uid in as a keyword. You can find it documented here. So, your url call would look like the following:
Show members near you
This case is, of course, explicitly supported and documented. You're missing the fact that everything inside a template tag is evaluated. You can just pass the uid in:
{% url 'show-members-near' uid=uid %}

How to pass a literal string value to the django url template tag

I have a URL conf such as this:
url(r'^value-toggle/(?P<profile_id>\d{1,10})/(?P<on_or_off>on|off)/$',
'clipfo.profile.views.value_toggle',
name='value-toggle'),
In my template, I am trying to link to it:
Turn off.
I get the following error when viewing the page which contains the url tag:
Caught NoReverseMatch while rendering: Reverse for
'value-toggle' with arguments '()' and keyword
arguments '{'profile_id': 5, 'on_or_off': '### FIX ME - bad template
variable ###'}' not found.
Please note that "### FIX ME - bad template variable ###" is my TEMPLATE_STRING_IF_INVALID value.
How can i pass a literal "off" as the value of named param on_or_off to the url django template tag?
The future has saved me!
Just called
{% load url from future %}
at the beginning of my template.
Using the url tag from future allowed me to do what I needed to do. I only had to wrap the name of the url in single quotes, such as:
Turn off.

identical views different URLs

I have following routs:
url(r'^future/programs/$', main.programs, {'period': 'future'}),
url(r'^past/programs/$', main.programs, {'period': 'past'}),
When I try to display link in template, using template tag url like this
{% url main.views.main.programs %}
I always get link /past/programs/. When I try like this
{% url main.views.main.programs period="future" %}
I get an error:
Caught NoReverseMatch while rendering: Reverse for
'main.views.main.programs' with arguments '()' and keyword arguments
'{'period': u'future'}' not found.
How i can display link to /future/programs/?
I think you might want to approach it with one single url pattern:
url(r'^(?P(<period>[\w]+)/programs/$', main.views.programs),
and in your view:
def programs(request, period):
if period == 'future':
...
elif period == 'past':
...
and in templates:
{% url main.views.main.programs period="future" %}
In your approach, you are mistaking the forward flow with the reverse flow, i.e. the extra keyword arguments of the url conf with the keyword arguments that are passed to match a pattern.
The former is extra data you are allowed to pass to a view when it is matched (i.e. when a user goes to /future/programs/, the pattern is matched and period=future is passed to the view), the latter is the actual data used to match the url (i.e. the period=future is passed to the reverse() function which tries to match a pattern that excepts those keyword arguments - which you haven't outlined)
Edit:
A more appropriate pattern to use in your url would be something like:
url(r'^(?P(<period>past|future)/programs/$', main.views.programs),
where the selection could only be 'past' or 'future'. This is fine for incoming urls, but django's reverse() function (which is used in the url template tag) can't handle alternative choices:
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
The main restriction at the moment is that the pattern cannot contain alternative choices using the vertical bar ("|") character.
I would rather assign each url a name:
url(r'^future/programs/$', main.programs,
{'period': 'future'},
name='future_programs'),
url(r'^past/programs/$', main.programs,
{'period': 'past'},
name='past_programs'),
And to display the link in your template:
Past programs: {% url past_programs %}
Future programs: {% url future_programs %}
I think this solution is better because if you just have two options for that view, you can forget about passing parameters and validating them.
Now, if those two options (future, past) can grow into several more, the other solution would be better, but I think this is not the case.

django pass extra option through url templatetag to view

I have the following line in my url file
url(r'^confirm/$', 'confirm', {'status':'live'}, name="confirm"),
As you can see I am passing the extra option status to the view which is described here
I would like to pass the status value through the template using the url templatetag. I tried
{% url confirm status='pending' %} but I get the following error:
Caught NoReverseMatch while rendering: Reverse for 'confirm' with arguments '()' and keyword arguments '{'status': u'pending'}' not found. Is it possible to do what I am trying to do?
How could this work? The url tag just outputs a URL that is valid in your urlconf and which maps the arguments into the URL. But your url has no place for alternative values for status - it's hard-coded.
If you want to pass parameters into a URL pattern, the pattern needs to have a space for the parameter.

Django - How to pass several arguments to the url template tag

In my urls.py I have:
(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/section/(?P<slug>[-\w]+)/$',
'paper.views.issue_section_detail',
{},
'paper_issue_section_detail'
),
and I'm trying to do this in a template:
{% url paper_issue_section_detail issue.pub_date.year,issue.pub_date.month,issue.pub_date.day,section_li.slug %}
but I get this error:
TemplateSyntaxError
Caught an exception while rendering: Reverse for 'paper_issue_section_detail' with arguments '(2010, 1, 22, u'business')' and keyword arguments '{}' not found.
However, if I change the URL pattern to only require a single argument it works fine. ie:
(r'^(?P<year>\d{4})/$',
'paper.views.issue_section_detail',
{},
'paper_issue_section_detail'
),
and:
{% url paper_issue_section_detail issue.pub_date.year %}
So it seems to complain when I pass more than a single argument using the 'url' template tag - I get the same error with two arguments. Is there a different way to pass several arguments? I've tried passing in named keyword arguments and that generates a similar error.
For what it's worth, the related view starts like this:
def issue_section_detail(request, year, month, day, slug):
How do I pass more than a single argument to the url template tag?
I had the same issue (I'm using Django 1.3.1) and tried Gregor Müllegger's suggestion, but that didn't work for two reasons:
there should be no commas between year, month and day values
my class-based generic view seems to take only keyword arguments
Thus the only working solution was:
{% url news_detail slug=object.slug year=object.date|date:"Y" month=object.date|date:"m" day=object.date|date:"d" %}
The problem lives in the /(?P<month>\d{2})/ part of your url configuration. It only allows exactly two digits (\d{2}) while issue.pub_date.month is only one digit.
You can do either allow also one digit in the URL (but this will violate the principle of unique URLs, /2010/1/... would be the same as /2010/01/...) or pass two digits to the month argument in your url templatetag.
You can use the date filter to achieve a consistent formating of date objects. Use the url tag like this:
{% url paper_issue_section_detail issue.pub_date|date:"Y",issue.pub_date|date:"m",issue.pub_date|date:"d",section_li.slug %}
Look at the month and day argument: It will be always displayed as two digits (with a leading zero if necessary). Have a look at the documentation of the now tag to see which options are possible for the date filter.
Your month expression is (?P<month>\d{2}), but you're sending it the argument 1. The 1 doesn't match \d{2}, so the url resolver isn't finding your view.
Try changing the month expression to \d{1,2} (or something to that effect).