from django.core.urlresolvers import RegexURLResolver
def extend(root_resolver, extra_parm_dct, require_matches=True):
'''
Extend a resolver to have extra parameters
passed in by a per-name basis, and also
validate that names exist so that child
application can essentially validate the API
of the app whose urls it is including
root_resolver: should be url w/include (see example below)
extra_parm_dct:
keys: should be names defined for reverse calls
values: dictionaries of extra parameters to be sent to views
require_matches: if True, raise exception if some names are not found
Limitations:
1) only tested on python 2.5, django 1.1
2) modifies resolvers directly, does not clone them
Example usage:
extend(url(r'', include('member.urls')),
{
'make_payment':
{'make_payment_form': QuickEnrollPaymentForm},
'home_page': {}, # simply must exist
}
),
'''
if not isinstance(root_resolver, RegexURLResolver):
raise TypeError('Expected RegexURLResolver argument')
names_to_extend = set(extra_parm_dct.keys())
def _extend(resolver):
for pattern in resolver.url_patterns:
if isinstance(pattern, RegexURLResolver):
_extend(pattern)
else:
name = pattern.name
if name in extra_parm_dct:
extra_args = extra_parm_dct[name]
pattern.default_args.update(extra_args)
names_to_extend.discard(name)
_extend(root_resolver)
if require_matches and len(names_to_extend) > 0:
raise Exception('The following names do not exist in extended urlconf: %s' % names_to_extend)
return root_resolver
Comments
See also:
http://www.djangosnippets.org/snippets/1378/
I wrote my snippet before seeing the snippet 1378. With a similar monkeypatch right into RegexURLResolver, you could rewrite extend to return a new object that calls into RegexURLResolver to do the heavy lifting and then supply the extra args in its own resolve() method.
#