Opened 11 years ago

Closed 11 years ago

Last modified 9 years ago

#240 closed defect (fixed)

get_callback() improvements

Reported by: maurycy Owned by: Jacob
Component: Core (Other) Version:
Severity: trivial Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


The problem was:

[maurycy@localhost ~]$ grep -A 2 INSTALLED_APPS session/settings/




[maurycy@localhost ~]$ cat session/settings/urls/

from django.conf.urls.defaults import *

urlpatterns = patterns('',

    (r'^session/', include('session.apps.session.urls.session')),


[maurycy@localhost ~]$ cat session/apps/session/urls/

from django.conf.urls.defaults import *

urlpatterns = patterns('',

    (r'^login/?$', 'session.apps.session.views.login'),

    (r'^logout/?$', 'session.apps.session.views.logout'),


[maurycy@localhost ~]$ ls -1 session/apps/session/views/*.py




[maurycy@localhost ~]$ export DJANGO_SETTINGS_MODULE='session.settings.main'

[maurycy@localhost ~]$ runserver

Starting server on port 8000 with settings module 'session.settings.main'.

Go to for Django.

Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

[31/Jul/2005 00:32:03] "GET /session/login HTTP/1.1" 302 0

[31/Jul/2005 00:32:03] "GET /session/login/ HTTP/1.1" 500 883

Where http://localhost:8000/session/login returns the exception:

There's been an error:

Traceback (most recent call last):

  File "/usr/lib/python2.4/site-packages/django/core/handlers/", line 57, in get_response

    callback, param_dict = resolver.resolve(path)

  File "/usr/lib/python2.4/site-packages/django/core/", line 81, in resolve

    match =

  File "/usr/lib/python2.4/site-packages/django/core/", line 59, in search

    sub_match =

  File "/usr/lib/python2.4/site-packages/django/core/", line 34, in search

    self.func = self.get_callback()

  File "/usr/lib/python2.4/site-packages/django/core/", line 42, in get_callback

    raise ViewDoesNotExist, "Tried %s. Error was: %s" % (self.callback, str(e))

ViewDoesNotExist: Tried session.apps.session.views.login. Error was: 'module' object has no attribute 'login'


05:30 < mmarshall> (r'^login/?$', 'session.apps.session.views.login.login')
05:31 < mmarshall> Try that.
05:31 < maurycypw> ugh?
05:31 < maurycypw> ugly, but works.
05:31 < mmarshall> hehe
05:31 < maurycypw> why it works?
05:31 -!- slightlyoff [~alex@] has joined #django
05:32 < mmarshall> Django must need a function name.
05:32 < mmarshall> All you were giving it was a module name.
05:32 < maurycypw> eh. it should be fixed
05:32 < maurycypw> next ticket, please!
05:32 < mmarshall> I guess that the error was so unhelpful because it only
                   looked for attributes that were functions.
05:33 < mmarshall> In this case, you had an attribute named 'login', but it was
                   another module.
05:33 < mmarshall> And yes, it should be fixed :D

Change History (7)

comment:1 Changed 11 years ago by Jacob

Resolution: invalid
Status: newclosed

Um... I'm not entirely sure what's supposed to be fixed here; a view must be a callable, and you can't call a module.

comment:2 Changed 11 years ago by mmarshall

priority: normallow
Resolution: invalid
Severity: normaltrivial
Status: closedreopened

The behavior is correct; the issue that maurycy had was that the error reported was confusing.

One possible solution, is for urlresolver to also check if the string given is a module (instead of just module+function.) If it is, try to get a function named 'default' from it. This results in a clearer error message. (and would have saved maurycy a fair amount of time.)

On the other hand, it might of been that he was up all night. :-/

Here is a patch to do this:

Index: django/core/
--- django/core/ (revision 356)
+++ django/core/ (working copy)
@@ -38,8 +38,14 @@
         mod_name, func_name = get_mod_func(self.callback)
             return getattr(__import__(mod_name, '', '', ['']), func_name)
-        except (ImportError, AttributeError), e:
+        except ImportError, e:
             raise ViewDoesNotExist, "Tried %s. Error was: %s" % (self.callback, str(e))
+        except AttributeError, e:
+            try:
+                return getattr(__import__(self.callback,'','',['']),"default")
+            except (ImportError, AttributeError), e:
+                raise ViewDoesNotExist, "Tried %s. Error was: %s" % (self.callback, str(e))

 class RegexURLMultiplePattern:
     def __init__(self, regex, urlconf_module):

comment:3 Changed 11 years ago by maurycy

Exactly. Thanks, mmarshall. I was so sleepy to describe this problem in the more detailed manner.

By the way, would be also nice to try not "default", but the same name of attribute as module. For example, "login" for module "login".

comment:4 Changed 11 years ago by Jacob

Owner: changed from Adrian Holovaty to Jacob
Status: reopenednew

Ah, I see. I'm less inclined to call a "default" function since that behavior would be non-obvious, but a better error message certainly is worth doing.

comment:5 Changed 11 years ago by Jacob

Status: newassigned

comment:6 Changed 11 years ago by Jacob

Resolution: fixed
Status: assignedclosed

(In [357]) Improved error message in urlresolvers (fixes #240)

comment:7 Changed 11 years ago by maurycy

Great, thanks!

Note: See TracTickets for help on using tickets.
Back to Top