Django URL kwargs both in main app and subapp, reverse fails - django

EDIT: Never mind, it was something completely unrelated (wrong URL name).
I have a Django urls.py that includes another urls.py from a subapp. I get "reverse not found" errors when trying to use reverse(). I use keyword arguments in the URL both before and after the include, it's basically:
First urls.py:
urlpatterns = patterns(
'',
# Change requests are in a subapp
url(r'^projects/(?P<project_slug>[^/]+)/changerequests/',
include('myapp.changerequests.urls')),
)
And in the subapp's urls.py:
urlpatterns = patterns(
'',
url(r'^detail/(?P<request_id>\d+)/$',
views.RequestDetailPage.as_view(),
name='changerequests_detail'),
)
Now I want to find an URL with something like
url = reverse('changerequests_detail', kwargs={
'project_slug': self.project.slug,
'request_id': str(self.id)})
So it uses two kwargs, that are spread out over both urls.pys. But the reverse fails to find an answer (Reverse for 'changerequests_main' with arguments '()' and keyword arguments '{u'project_slug': u'123-2013_monitoring_slibaanwas-hdsr', u'request_id': '2'}' not found.).
Is that the problem? Is spreading kwargs over urls files this way not possible?

Maybe error occurs because it's trying to reverse 'changerequests_main' URL, not 'changerequests_detail'.

Related

Using a name for dummy url patterns in django

I have a project with an app named exams. Right now my index page is the index page of one of these apps. So the url patterns is something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams")),
)
However it is possible that in future I want to create a new view for my index page and change the url patterns to something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', 'mysite.views.index', name="index"),
)
I want to create some links in my template to index whether it loads the exams app or another view. So I tried to use the name argument for the url method(like above) but it seems it's not working. When I use {% url 'index' %} in my template it returns the following error:
Reverse for 'index' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
UPD: I forgot to mention that I tried using the following code:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams"), name="index"),
)
And I got the error I wrote above.
UPD2: To clarify the problem more:
Right now when I go to http://mydomain/ I'll see my app index. But maybe in the future I like to change my index page and use another view for creating it. So when I go to http://mydomain/ I'll see the page rendered by that view and by going to http://mydomain/exams I'll see my apps index pages. In that case my urls.py will be sth like the second code I wrote above in which I can easily link to index page using {% url 'index' %} tag. However for now I'm using the code I wrote in my first update. I want my templates to render {% url 'index' %} as a link to my index page(instead of using {% url 'exams:index' %} so when I later change the urls.py code I won't have to change all of my templates.
If I understand well, you want an index view that could be easily changed, while not changing the links pointing to it in your templates. You can use your index view as a wrapper for other views ie:
def a_view_that_will_show_all_the_exams(request):
# this is the page displayed for now as default, but this could change
# some logic here
def another_view_that_could_become_the_home_page(request):
# some logic here
def index(request):
return a_view_that_will_show_all_the_exams(request)
# or another_view_that_could_become_the_home_page
# or return exams.views.whatever_view
This way you can easily change the result of the index view while keeping your links static.
If I understood you correctly, right now you don't have a url with the name index, in his case it is normal that when the template renders, it tries to find a url named index, and when it doesn't find it, it fails. What you might need is create the url and redirect to another view for now, like explained here:
Redirect to named url pattern directly from urls.py in django?
UPDATE:
I'm still not completely sure of what you want (sorry about that), but I suspect what you want to do is something similar to this:
from django.conf.urls import patterns, include, url
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', RedirectView.as_view(url=reverse_lazy('exams:index'), name="index"),
)
The solution that Raphael is giving you is similar, but the user will not be redirected (with both urls the user will see the same content). Maybe that is what you are looking for?

Redirect with parameters. NoReverseMatch at /test/

views.py:
def demo(request, **kwargs):
print response
......
def test(request):
......
kwargs = {'response': response}
return redirect('demo', **kwargs)
urls.py:
from django.conf.urls import patterns, url
from django.contrib.sitemaps.views import sitemap
urlpatterns = patterns('clients.views',
url(r'^test/', 'test', name='test'),
url(r'^demo/', 'demo', name='demo'),
)
Why I have this error:
NoReverseMatch at /test/
Reverse for 'demo' with arguments '()' and keyword arguments
'{'response': {u'status': u'ok'}}' not found.
Request Method: POST Request URL: http ://127.0.0.1:8000/test/
When using the redirect() shortcut you're actually doing a HttpResponseRedirect() and therefore need not to include the response in your kwargs.
Furthermore if you would like to redirect with keyworded arguments then the call would be
redirect('/myurl/', momma="im comin' home")
or
redirect('/myurl/', kwargs={'loads_a_kwargs':'cowboy'})
The error you're getting is because your regexp url(r'^demo/', 'demo', name='demo') does not accept any parameters. Also, normally you would end all your url regexes with $ to denote that the capturing should stop.
Thats error simply been raised not from your test view but from your demo view. As per url reverse matching .. demo url must match to the demo view function parameters.
for example : url : demo/ should be demo/<response>
And In case you don't want to change the url pattern then make your response as GET parameter to demo view.
When you say redirect('demo', **kwargs), internally its trying to find the urlpattern demo/(?P<response>\d+). Actually it could be either \d+ or \w+ or whatever. But you don't have this urlpattern defined and so its failing.
So, it will pass if you define such url pattern. But another problem with your code is that response in kwargs is a dictionary and there is no way you can capture a dictionary in the url pattern.
Any particular reason you want to redirect to demo along with status code?
NoReverseMatch Exception Occurs when a matching URL in your URLconf cannot be identified based on the parameters you have given. Refer the django Docs https://docs.djangoproject.com/en/dev/ref/exceptions/#noreversematch
I am looking at your url.py You didn't included $
url(r'^test/$', 'test', name='test'),

Why is the url function used more often in Django 1.5 documentation?

I'm working with some older Django code and the url function is not used anywhere, similar to the examples in the Django 1.4 documentation:
from django.conf.urls import patterns, url, include
urlpatterns = patterns('',
(r'^articles/2003/$', 'news.views.special_case_2003'),
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
but I notice in the Django 1.5 documentation the url function is used frequently:
from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^articles/2003/$', 'news.views.special_case_2003'),
url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
Why is this? Is it a matter of convention, or is there a technical reason to use the url function? Which practice should I follow in the future, and how should I maintain my legacy code without url calls?
From the docs
url(regex, view, kwargs=None, name=None, prefix='')
You can use the url() function, instead of a tuple, as an argument to patterns(). This is convenient if you want to specify a name without the optional extra arguments dictionary. For example:
urlpatterns = patterns('',
url(r'^index/$', index_view, name="main-view"),
...
)
And you use them for reverse URL matching (again, the docs)
You could convert the first example as:
url(r'^articles/2003/$', special_case_2003, name="special_case_2003"),
and call it in your template
{% url special_case_2003 %}
Yeah, maybe the two examples you posted are a bit too fuzzy about this

NoReverseMatch exception in Django

I've got this urls.py :
urlpatterns = patterns('',
# Plugin actions
url(r'plugin/((?P<slug>[a-zA-Z0-9_\-]*)/)?$', PluginView.as_view(), name='wa-plugin'),
)
Then when I use reverse :
reverse('wa-plugin', args=[u'plugin-header-1'])
or even
reverse('wa-plugin', kwargs={'slug':u'plugin-header-1'})
I get
NoReverseMatch: Reverse for 'wa-plugin' with arguments
'('plugin-header-1',)' and keyword arguments '{}' not found.
Do you have any ideas of how I can make it works ?
if the problem is the optional argument, one way around that is to define two url entries (to the same view):
urlpatterns = patterns('',
# Plugin actions
url(r'plugin/$', PluginView.as_view(), name='wa-plugin'),
url(r'plugin/(?P<slug>[a-zA-Z0-9_\-]*)/$', PluginView.as_view(), name='wa-plugin'),
)
(pretty sure you can even use the same name, since they have different "signatures (kwargs)")
It seams that reverse doesn't like the optional arguments.
You should use :
urlpatterns = patterns('',
# Plugin actions
url(r'plugin/$', PluginView.as_view(), name='wa-plugin'),
url(r'plugin/(?P<slug>[a-zA-Z0-9_\-]*)/$', PluginView.as_view(), name='wa-plugin-slug'),
)
Then reverse works both with args and kwargs

Django Caught NoReverseMatch - TemplateSyntaxError

I got this error, but can't seem to figure it out. I copied it directly from a previous Django project, hence part of the confusion.
TemplateSyntaxError at Caught NoReverseMatch while rendering: Reverse for 'about' with arguments '()' and keyword arguments '{}' not found.
In my index.html, I have a link to {% url about %} didn't link to the about.html template
Urls.py has this:
urlpatterns = patterns('django.views.generic.simple',
url(r'^about/$', 'direct_to_template', {"template":"about.html"}, name="about"),
)
The problem was my second urlpattern was overriding the first pattern.
Instead of:
urlpatterns = patterns('',
it needed to be:
urlpatterns += patterns('',
The url regex is expecting an ending slash. Does the offending url end with a slash?
If you do have a PREPEND_SLASHES settings differing from your last projects, that might explain the error you're seeing!
Your url is ok. You need to check two things:
Is the urls.py included from the main urls.py?
Is the application added to INSTALLED_APPLICATIONS in settings.py?