Django reverse() in get_absolute_url() doesn't work - django

I am trying to use the reverse function in get_absolute_url() and it is not finding the correct reverse match for the view. My url.py doesn't have any errors because I can access that view through the url "traildetail/4" etc and all the other urls are working fine.
I have a following view function:
def get_trail_detail(request, trail_id=None):
'''
'''
return HttpResponse(str(trail_id))
I also have the following url defined in urls.py.
url(r'^traildetail/(?P<trail_id>\d{1,5})/$', 'get_trail_detail', name='get-trail-detail'),
So when I run the following code in the django shell I get the NoReverseMatch error:
reverse('trails.views.get_trail_detail',None, kwargs={'trail_id': '3'})
reverse('trails.views.get_trail_detail', args=[str(1)])
reverse('trails.views.get_trail_detail', kwargs={'trail_id': '3'})
I get the following Error: for all of the above attempts:
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py", line 416, in _reverse_with_prefix
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'trails.views.get_trail_detail' with arguments '()' and keyword arguments '{'trail_id': '3'}' not found
enter code here

For future reference - You can access the url like this:
reverse('get-trail-detail', kwargs={'trail_id': 3})

Related

URL resolution issues in Django Tests

I've written a django model that has a get_absolute_url method, with unit tests to make sure everything is kosher. The get_absolute_url tests pass no problem. The get_absolute_url method is written as so
def get_absolute_url(self):
return reverse("scheduling:klass", args=[self.pk])
This is the url routing to give context about how the urls flow.
#main.urls
urlpatterns = [
url(r'^$', homepage, name="home"),
url(r'^scheduling/', include('scheduling.urls', namespace="scheduling")),
url(r'^profile/', include('user_profile.urls', namespace="profile")),
url(r'^accounts/', include('allauth.urls')),
url(r'^admin/', admin.site.urls),
]
#scheduling.urls
urlpatterns = [
url(r'add-class/$', views.add_klass, name="add_klass"),
url(r'class/(?P<pk>\d+)/$', views.klass, name="klass"),
]
I'm testing the klass view (it's basically just a klass detail view) as follows
def test_klass_detail_template_renders(self):
print(self.klass.pk)
response = self.client.get(self.klass.get_absolute_url())
self.assertTemplateUsed(response, "scheduling/klass.html")
The test fails with the following stacktrace.
======================================================================
ERROR: test_klass_detail_template_renders (scheduling.tests.test_views.KlassViewTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/core/urlresolvers.py", line 586, in reverse
extra, resolver = resolver.namespace_dict[ns]
KeyError: 'myproject.profile'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/template/defaulttags.py", line 507, in render
current_app=current_app)
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/core/urlresolvers.py", line 596, in reverse
key)
django.core.urlresolvers.NoReverseMatch: 'myproject.profile' is not a registered namespace
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/me/Documents/Development/myproject/src/scheduling/tests/test_views.py", line 60, in test_klass_detail_template_renders
response = self.client.get(self.klass.get_absolute_url())
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/test/client.py", line 503, in get
**extra)
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/test/client.py", line 304, in get
return self.generic('GET', path, secure=secure, **r)
...
File "/Users/me/.virtualenvs/myproject/lib/python3.5/site-packages/django/core/urlresolvers.py", line 508, in _reverse_with_prefix
(lookup_view_s, args, kwargs, len(patterns), patterns))
django.core.urlresolvers.NoReverseMatch: Reverse for 'profile' with arguments '('',)' and keyword arguments '{}' not found. 2 pattern(s) tried: ['profile/$', 'profile/(?
P<username>[\\w+-.#]+)/$']
It implies that that get_absolute_url is passing the pk value of the klass model to the url pattern but it works when I test it manually and it works in literally every other situation.
This...is...a...head scratcher. Any help is appreciated.
UPDATE
I think it might have to do with test isolation. I've done some print debugging and found that each test creates a new instance of the klass model.
Here are my setUp and tearDown methods.
class KlassViewTests(TestCase):
def setUp(self):
self.factory = ClassMateFactory()
self.teacher = self.factory.create_teacher("Maria")
self.linked_student = self.factory.create_student(
"Milhouse",
self.teacher.profile
)
self.klass = self.factory.create_klass(
"Test Klass",
teachers=self.teacher.profile,
students=self.linked_student.profile
)
self.data = {
"name": "New Test Class",
"status": "A",
"students": [self.linked_student.profile.pk],
"teachers": [self.teacher.profile.pk]
}
super().setUp()
def tearDown(self):
print(self.klass.get_absolute_url())
self.teacher.delete()
self.linked_student.delete()
self.klass.delete()
super().tearDown()
Hopefully this helps clear things up.
EDIT
Added the url conf to provide more context
With the current state of your question it looks like a copy paste error. Why I think this:
The error is described by Django as:
django.core.urlresolvers.NoReverseMatch:
Reverse for 'profile' with arguments '('',)' and keyword arguments '{}' not found.
2 pattern(s) tried: ['profile/$', 'profile/(?P<username>[\\w+-.#]+)/$']
You have omitted part of the stack trace so I cannot be sure but the line that causes this error in your code is:
response = self.client.get(self.klass.get_absolute_url())
The model in question seems not to be profile but something called klass.
Seems...
It could also be that self.klass at this point actually refers to a profile (of a teacher or student) and that is why it uses the profile's get_absolute_url.
tl;dr I think you just need to thoroughly read through all of your code (maybe get some second pair of eyes) to find the little mistypings.

redirect error with django

I have a problem with the redirect of Django 1.4.3
#-*- coding: utf-8 -*-
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
def redirect_test(request):
print("redirect_test() called.")
return redirect('redirectionFunc')
def redirectionFunc(request):
return HttpResponse("You have been redirected.")
My url is :
url(r'^redirectTest/$', 'redirect_test')
When I try to open
http://xxx/blogz/redirectTest
I got the following error :
NoReverseMatch at /blogz/redirectTest/
Reverse for 'redirectionFunc' with arguments '()' and keyword arguments '{}' not found.
Whereas the terminal I have :
redirect_test() called.
What's wrong ??
The 'redirect' method, takes the python path to the url, or the name of the url.
In the first case, if your "redirect_func" view is in app/views.py, your code should be:
return redirect('app.views.redirect_func')
If you want to name your url, for example "redirect_test", in your url configuration you should give the name parameter to the url method:
url(r'^redirectTest/$', 'app.views.redirect_func', name='redirect_test')
Then you can call redirect with the name of your url:
return redirect('redirect_test')
You can check the documentation on naming urls here

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'),

Frustrating NoReverseMatch Found

I'm having a tough time debugging this particular error. I have the following in my urls.py:
url(r'^report/(?P<share_url>\w+)/$', 'share',
name='share'),
url(r'^report/(?P<share_url>\w+)/revoke/$', 'share_revoke',
name='share_revoke'),
In views.py I have:
def share(request, share_url):
...
#login_required
def share_revoke(request, share_url):
...
In my template I have:
<a href='{% url share share_url %}'>Share</a>
<a href='{% url share_revoke share_url %}'>Revoke</a>
When I try and load this template, I get a NoReverseMatch:
NoReverseMatch at /mypath/
Reverse for 'share_revoke' with arguments '(u'Sh4rE',)' and keyword arguments '{}' not found.
Why is it failing for the second url and not the first? I am logged in.
Trying this on the shell:
>>> reverse('share',args=(u'klajsdf',))
'/report/klajsdf/'
>>> reverse('share_revoke',args=(u'klajsdf',))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/ubuntu/virt/virt1/local/lib/python2.7/site-packages/django/core/urlresolvers.py", line 476, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "/home/ubuntu/virt/virt1/local/lib/python2.7/site-packages/django/core/urlresolvers.py", line 396, in _reverse_with_prefix
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'share_revoke' with arguments '(u'klajsdf',)' and keyword arguments '{}' not found.
This was a non-issue in the end. My problem was SublimeText2 SFTP had got confused and wasn't overwriting the urls.py on my server, hence the large amount of wtf.

Monkey patched django auth's login, now its tests fail

My app seeks to wrap the django.contrib.auth.views login and logout views with some basic auditing/logging capabilities. I'm following the prescription as described in the django-axes project, and in running on a server and some other tests, it works as expected, transparently without issue.
The code goes like this:
from django.contrib.auth import views as auth_views
from myapp.watchers import watch_login
class WatcherMiddleware(object):
def __init__(self):
auth_views.login = watch_login(auth_views.login)
And
def watch_login(func):
def decorated_login(request, *args, **kwargs):
#do some stuff
response = func(request, *args, **kwargs)
#more stuff
return response
return decorated_login
Urls:
#Edit: Added project's urls - just using vanilla django's auth login
(r'^accounts/login/$', 'django.contrib.auth.views.login',{"template_name":settings.LOGIN_TEMPLATE }),
However, in our build workflow, we run into some issues in the django.contrib.auth.tests.views.
Specifically, these are the tests that fail in django.contrib.auth:
ERROR: test_current_site_in_context_after_login (django.contrib.auth.tests.views.LoginTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python26\lib\site-packages\django\contrib\auth\tests\views.py", line 192, in test_current_site_in_context_after_login
response = self.client.get(reverse('django.contrib.auth.views.login'))
File "C:\Python26\lib\site-packages\django\core\urlresolvers.py", line 351, in reverse
*args, **kwargs)))
File "C:\Python26\lib\site-packages\django\core\urlresolvers.py", line 297, in reverse
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'myapp.watchers.decorated_login' with arguments '()' and keyword arguments '{}' not found.
======================================================================
ERROR: test_security_check (django.contrib.auth.tests.views.LoginTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python26\lib\site-packages\django\contrib\auth\tests\views.py", line 204, in test_security_check
login_url = reverse('django.contrib.auth.views.login')
File "C:\Python26\lib\site-packages\django\core\urlresolvers.py", line 351, in reverse
*args, **kwargs)))
File "C:\Python26\lib\site-packages\django\core\urlresolvers.py", line 297, in reverse
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'myapp.watchers.decorated_login' with arguments '()' and keyword arguments '{}' not found.
Only these two tests fail with the inclusion of the wrapped login monkey patch.
It seems like the reverse() call in the django auth test behaves differently than how an unpatched function does its thing.
The reason why we're going this route for wrapping logging vs. using django 1.3's new authentication signals is because the logging method provided there only tells you if a wrong attempts happens - it doesn't give you access to the request object to log additional information around that improper request. Patching the authentication form in that case would not have been helpful, hence our need to wrap the login function.
Am I doing something wrong with my wrap of the login function? Or is this as to be expected with tests failing due to other side effects, despite no change in overall functionality?
edit: I'm running python 2.6.4, django 1.2.5
Couldn't you simply wrap it in another view?
urls:
url(
r'^accounts/login/$',
'accounts.views.login',
{"template_name":settings.LOGIN_TEMPLATE }
),
accounts.views:
from django.contrib.auth import views as auth_views
def login(request, *args, **kwars):
# do some stuff
response = auth_views.login(request, *args, **kwars)
# more stuff
return response
Like this, django.contrib.auth.tests will be testing the view which they were written for and you can write your own tests for the "more stuff" you need.
I suspect this is the same underlying issue that affects django-registration in that the test runner only imports the URLs of the app being tested at the time -- ie, contrib.auth and not myapp There are various tickets about things similar to this issue but a quick scan of them implies the solution is to decouple things, which isn't going to be viable for your solution I'm guessing.
Another way around it would be to use Fabric file or Makefile to trigger a subset of tests, avoiding the two that fail because of your monkeypatch, and then add two alternate ape-friendly tests to replace them.