Dave Perrett

NoReverseMatch : Custom Registration Templates Break Django Unit Tests

django, programming, python, quickie, web

I’ve over-ridden several of the built-in django auth and bitbucket.org/ubernostrum/django-registration/ templates so I can have my own custom-styled login and registration pages. This all worked fine until i tried to run the built-in django and django_registration test suites, when everything fell apart :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
======================================================================
ERROR: test_confirm_different_passwords (django.contrib.auth.tests.views.PasswordResetTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dave/Documents/Code/python/loudgallery/django/contrib/auth/tests/views.py", line 124, in test_confirm_different_passwords
    'new_password2':' x'})
  File "/Users/dave/Documents/Code/python/loudgallery/django/test/client.py", line 313, in post
    response = self.request(**r)
  File "/Users/dave/Documents/Code/python/loudgallery/django/core/handlers/base.py", line 92, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/Users/dave/Documents/Code/python/loudgallery/django/contrib/auth/views.py", line 141, in password_reset_confirm
    return render_to_response(template_name, context_instance=context_instance)
  File "/Users/dave/Documents/Code/python/loudgallery/django/shortcuts/__init__.py", line 20, in render_to_response
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/loader.py", line 108, in render_to_string
    return t.render(context_instance)
  File "/Users/dave/Documents/Code/python/loudgallery/django/test/utils.py", line 29, in instrumented_test_render
    return self.nodelist.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 779, in render
    bits.append(self.render_node(node, context))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 792, in render_node
    return node.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/loader_tags.py", line 97, in render
    return compiled_parent.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/test/utils.py", line 29, in instrumented_test_render
    return self.nodelist.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 779, in render
    bits.append(self.render_node(node, context))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 792, in render_node
    return node.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 946, in render
    autoescape=context.autoescape))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 779, in render
    bits.append(self.render_node(node, context))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 792, in render_node
    return node.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/loader_tags.py", line 24, in render
    result = self.nodelist.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 779, in render
    bits.append(self.render_node(node, context))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 792, in render_node
    return node.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/defaulttags.py", line 244, in render
    return self.nodelist_false.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 779, in render
    bits.append(self.render_node(node, context))
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/__init__.py", line 792, in render_node
    return node.render(context)
  File "/Users/dave/Documents/Code/python/loudgallery/django/template/defaulttags.py", line 382, in render
    raise e
NoReverseMatch: Reverse for '<function index at 0x1ca9c30>' with arguments '()' and keyword arguments '{}' not found.

There were quite a few more of these, including :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test_activation_success_url (registration.tests.views.RegistrationViewTests) ... ERROR
test_activation_template_name (registration.tests.views.RegistrationViewTests) ... ERROR
test_registration_disallowed_url (registration.tests.views.RegistrationViewTests) ... ERROR
test_registration_extra_context (registration.tests.views.RegistrationViewTests) ... ERROR
test_registration_success_url (registration.tests.views.RegistrationViewTests) ... ERROR
test_registration_template_name (registration.tests.views.RegistrationViewTests) ... FAIL
test_registration_view_closed (registration.tests.views.RegistrationViewTests) ... ERROR
test_registration_view_failure (registration.tests.views.RegistrationViewTests) ... FAIL
test_registration_view_initial (registration.tests.views.RegistrationViewTests) ... FAIL
test_registration_view_success (registration.tests.views.RegistrationViewTests) ... ERROR
test_valid_activation (registration.tests.views.RegistrationViewTests) ... ERROR
...
test_confirm_complete (django.contrib.auth.tests.views.PasswordResetTest) ... FAIL
test_confirm_invalid (django.contrib.auth.tests.views.PasswordResetTest) ... FAIL
test_confirm_valid (django.contrib.auth.tests.views.PasswordResetTest) ... FAIL
...

… and so on. After some investigation, it seems these errors occur because I have links to my own views in these custom templates, for example :

1
<a href="{% url home.views.index %}">Cancel</a>

For whatever reason, django doesn’t include my project’s various urls.py files when it runs its tests, so it doesn’t know anything about my URLs. After a few hours I found this solution, which is a little hack-y, but seems to work. Simply add as xxxx at the end of your url call, and output the url as a variable using (for example) . This seems to suppress the errors :

1
<a href="{% url home.views.index as index %}{{ index }}">Cancel</a>