id,summary,reporter,owner,description,type,status,component,version,severity,resolution,keywords,cc,stage,has_patch,needs_docs,needs_tests,needs_better_patch,easy,ui_ux 11190,urlresolvers.reverse: possibilities = self.reverse_dict.getlist(lookup_view) is empty but everything else seems to work,deltapass@…,nobody,"I've think i've found a bug with urlresolvers.reverse() (in use with permalink). I've tried to get this code working: {{{ _CONTENT_VIEW = ""page.views.view_by_content"" _CONTENT_VIEW_KWARG_ID_NAME = ""content_id"" *snip* # Point to content with default id @property @models.permalink def link(self): """"""Return link to content with Page calculated default content id. """""" return (self._CONTENT_VIEW, (), {self._CONTENT_VIEW_KWARG_ID_NAME: self.to_object.get_default_content_id()}) }}} And some method that is similar but in another subclass from this classes superclass. My urls.py and page/urls.py are looking like this: {{{ urlpatterns = patterns('', # Example: # (r'^evankproj/', include('evankproj.foo.urls')), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: # (r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: (r'^admin/(.*)', admin.site.root), (r""^content/"", include(""evankproj.page.urls"")), *snip* }}} and {{{ urlpatterns = patterns(""evankproj.page.views"", (r""^$"", ""index""), (r""^(?P\d+)/$"", ""view_by_content""), ) }}} Here is a pdb session where i tried to track down the problem, I entered from within my link method: {{{ Quit the server with CONTROL-C. > *snip*page/models.py(258)link() -> return (self._CONTENT_VIEW, (), (Pdb) up > /usr/lib/pymodules/python2.5/django/db/models/__init__.py(29)inner() -> bits = func(*args, **kwargs) (Pdb) list 24 (viewname, viewargs) 25 (viewname, viewargs, viewkwargs) 26 """""" 27 from django.core.urlresolvers import reverse 28 def inner(*args, **kwargs): 29 -> bits = func(*args, **kwargs) 30 return reverse(bits[0], None, *bits[1:3]) 31 return inner [EOF] (Pdb) list 20 15 ADD, CHANGE, BOTH = 1, 2, 3 16 17 def permalink(func): 18 """""" 19 Decorator that calls urlresolvers.reverse() to return a URL using 20 parameters returned by the decorated function ""func"". 21 22 ""func"" should be a function that returns a tuple in one of the 23 following formats: 24 (viewname, viewargs) 25 (viewname, viewargs, viewkwargs) (Pdb) next > /usr/lib/pymodules/python2.5/django/db/models/__init__.py(30)inner() -> return reverse(bits[0], None, *bits[1:3]) (Pdb) p bits ('page.views.view_by_content', (), {'content_id': 1}) (Pdb) p bits[1:3] ((), {'content_id': 1}) (Pdb) next NoReverseMatch: NoRevers...found."",) > /usr/lib/pymodules/python2.5/django/db/models/__init__.py(30)inner() -> return reverse(bits[0], None, *bits[1:3]) (Pdb) down > /usr/lib/pymodules/python2.5/django/core/urlresolvers.py(254)reverse() -> *args, **kwargs))) (Pdb) list 249 args = args or [] 250 kwargs = kwargs or {} 251 if prefix is None: 252 prefix = get_script_prefix() 253 return iri_to_uri(u'%s%s' % (prefix, get_resolver(urlconf).reverse(viewname, 254 -> *args, **kwargs))) 255 256 def clear_url_caches(): 257 global _resolver_cache 258 global _callable_cache 259 _resolver_cache.clear() (Pdb) p prefiyx *** NameError: NameError(""name 'prefiyx' is not defined"",) (Pdb) prefix u'/' (Pdb) down > /usr/lib/pymodules/python2.5/django/core/urlresolvers.py(243)reverse() -> ""arguments '%s' not found."" % (lookup_view, args, kwargs)) (Pdb) p lookup_view (Pdb) p lookup_view(1) *** TypeError: TypeError('view_by_content() takes exactly 2 arguments (1 given)',) (Pdb) p lookup_view(""x"", content_id=1) (Pdb) list 238 unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) 239 candidate = result % unicode_kwargs 240 if re.search(u'^%s' % pattern, candidate, re.UNICODE): 241 return candidate 242 raise NoReverseMatch(""Reverse for '%s' with arguments '%s' and keyword "" 243 -> ""arguments '%s' not found."" % (lookup_view, args, kwargs)) 244 245 def resolve(path, urlconf=None): 246 return get_resolver(urlconf).resolve(path) 247 248 def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): (Pdb) p args () (Pdb) kwargs {'content_id': 1} (Pdb) p lookup_view(*(), **kwargs) *** TypeError: TypeError('view_by_content() takes exactly 2 non-keyword arguments (0 given)',) (Pdb) p lookup_view(""x"", **kwargs) (Pdb) list 249 args = args or [] 250 kwargs = kwargs or {} 251 if prefix is None: 252 prefix = get_script_prefix() 253 return iri_to_uri(u'%s%s' % (prefix, get_resolver(urlconf).reverse(viewname, 254 *args, **kwargs))) 255 256 def clear_url_caches(): 257 global _resolver_cache 258 global _callable_cache 259 _resolver_cache.clear() (Pdb) down *** Newest frame (Pdb) list 260 _callable_cache.clear() 261 262 def set_script_prefix(prefix): 263 """""" 264 Sets the script prefix for the current thread. 265 """""" 266 if not prefix.endswith('/'): 267 prefix += '/' 268 _prefixes[currentThread()] = prefix 269 270 def get_script_prefix(): (Pdb) list cur *** Error in argument: 'cur' (Pdb) list 24 19 20 try: 21 reversed 22 except NameError: 23 from django.utils.itercompat import reversed # Python 2.3 fallback 24 from sets import Set as set 25 26 _resolver_cache = {} # Maps urlconf modules to RegexURLResolver instances. 27 _callable_cache = {} # Maps view and url pattern names to their view functions. 28 29 # SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for (Pdb) list 243 238 unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) 239 candidate = result % unicode_kwargs 240 if re.search(u'^%s' % pattern, candidate, re.UNICODE): 241 return candidate 242 raise NoReverseMatch(""Reverse for '%s' with arguments '%s' and keyword "" 243 -> ""arguments '%s' not found."" % (lookup_view, args, kwargs)) 244 245 def resolve(path, urlconf=None): 246 return get_resolver(urlconf).resolve(path) 247 248 def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): (Pdb) list 238 233 unicode_args = [force_unicode(val) for val in args] 234 candidate = result % dict(zip(params, unicode_args)) 235 else: 236 if set(kwargs.keys()) != set(params): 237 continue 238 unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) 239 candidate = result % unicode_kwargs 240 if re.search(u'^%s' % pattern, candidate, re.UNICODE): 241 return candidate 242 raise NoReverseMatch(""Reverse for '%s' with arguments '%s' and keyword "" 243 -> ""arguments '%s' not found."" % (lookup_view, args, kwargs)) (Pdb) p params *** NameError: NameError(""name 'params' is not defined"",) (Pdb) p set(params) *** NameError: NameError(""name 'params' is not defined"",) (Pdb) p kwargs {'content_id': 1} (Pdb) dict(k, force_unicode(v)) for k, v in kwargs.items()) *** SyntaxError: invalid syntax (, line 1) (Pdb) dict((k, force_unicode(v)) for k, v in kwargs.items()) {'content_id': u'1'} (Pdb) list 230 225 except (ImportError, AttributeError), e: 226 raise NoReverseMatch(""Error importing '%s': %s."" % (lookup_view, e)) 227 possibilities = self.reverse_dict.getlist(lookup_view) 228 for possibility, pattern in possibilities: 229 for result, params in possibility: 230 if args: 231 if len(args) != len(params): 232 continue 233 unicode_args = [force_unicode(val) for val in args] 234 candidate = result % dict(zip(params, unicode_args)) 235 else: (Pdb) p possibilities [] (Pdb) p self (Pdb) p self.reverse_dict .*)$'), ([(u'css/%(path)s', ['path'])], 'css/(?P.*)$'), ([(u'content/%(content_id)s/', ['content_id'])], 'content/(?P\\d+)/$'), ([(u'content/', [])], 'content/$'), ([(u'admin/%(_0)s', ['_0'])], 'admin/(.*)')], : [([(u'content/', [])], 'content/$')], : [([(u'content/%(content_id)s/', ['content_id'])], 'content/(?P\\d+)/$')], : [([(u'images/%(path)s', ['path'])], 'images/(?P.*)$'), ([(u'css/%(path)s', ['path'])], 'css/(?P.*)$')], >: [([(u'admin/%(_0)s', ['_0'])], 'admin/(.*)')]}> (Pdb) p self.reverse_dict.getlist(lookup_view) [] }}} As far as i could see, property is no problem in conjunction with permalink, as an inner func gets created and returned. Also, get_absolute_url as name is no requirement for permalink (as you may think after reading the permalink documentation). So, technically this should work. The function view_by_content gets found, so searching for it works. possibilities is empty, which is self.reverse_dict.getlist(lookup_view), so here seems to be the bug (if it is one). The for loop never gets entered and the raise statements gets executed. The problem seems to be completly related about this, as this is a change i just made in my mercurial (revision control) repository and nothing but this changed.",,closed,Core (Other),1.0,,invalid,urlresolvers reverse possibilities self.reverse_dict.getlist() permalink,'1.0.2 final' debian version,Unreviewed,0,0,0,0,0,0