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 set to invalid
  • Status changed from new to closed

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 changed from normal to low
  • Resolution invalid deleted
  • Severity changed from normal to trivial
  • Status changed from closed to reopened

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 to jacob
  • Status changed from reopened to new

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 changed from new to assigned

comment:6 Changed 11 years ago by jacob

  • Resolution set to fixed
  • Status changed from assigned to closed

(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