Opened 19 years ago

Closed 19 years ago

Last modified 17 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: no UI/UX: no

Description

The problem was:

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

INSTALLED_APPS = (

    'session.apps.session',

)

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

from django.conf.urls.defaults import *



urlpatterns = patterns('',

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

)

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

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

session/apps/session/views/__init__.py

session/apps/session/views/login.py

session/apps/session/views/logout.py

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

[maurycy@localhost ~]$ django-admin.py runserver

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

Go to http://127.0.0.1:8000/ 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/base.py", line 57, in get_response

    callback, param_dict = resolver.resolve(path)



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

    match = pattern.search(app_path)



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

    sub_match = pattern.search(new_path)



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

    self.func = self.get_callback()



  File "/usr/lib/python2.4/site-packages/django/core/urlresolvers.py", 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'

Discussion:

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@12.180.45.190] 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 by Jacob, 19 years ago

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 by mmarshall, 19 years ago

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/urlresolvers.py
===================================================================
--- django/core/urlresolvers.py (revision 356)
+++ django/core/urlresolvers.py (working copy)
@@ -38,8 +38,14 @@
         mod_name, func_name = get_mod_func(self.callback)
         try:
             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 by maurycy, 19 years ago

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 by Jacob, 19 years ago

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 by Jacob, 19 years ago

Status: newassigned

comment:6 by Jacob, 19 years ago

Resolution: fixed
Status: assignedclosed

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

comment:7 by maurycy, 19 years ago

Great, thanks!

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