- August 25, 2011
- urls urlconf urlpatterns decorator resolve
- 2 (after 2 ratings)
Apply a decorator to every urlpattern and URLconf module returned by Django's include() method . This allows you use a decorator on any number of views without having to decorate each one individually.
The use case here is wrapping all of the Django Admin with a superuser decorator. This is code that's better left alone where we can't actually go in and decorate the Admin views and urlpatterns manually. It's also almost guaranteed the Admin will include() other URL files. So the added bonus is all the INSTALLED_APPS that have their admin.py files registered by admin.autodiscover() will be decorated automatically as well.
This snippet is greatly inspired by @miracle2k's excellent #532. In the comments there @timbroder offers a modification to decorate includes but I think this is cleaner, simpler code and not subject to changes in the Django base code driving _get_url_patterns().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver from django.conf.urls.defaults import patterns, url, include from django.contrib import admin from myproject.myapp.decorators import superuser_required class DecoratedURLPattern(RegexURLPattern): def resolve(self, *args, **kwargs): result = super(DecoratedURLPattern, self).resolve(*args, **kwargs) if result: result.func = self._decorate_with(result.func) return result class DecoratedRegexURLResolver(RegexURLResolver): def resolve(self, *args, **kwargs): result = super(DecoratedRegexURLResolver, self).resolve(*args, **kwargs) if result: result.func = self._decorate_with(result.func) return result def decorated_includes(func, includes, *args, **kwargs): urlconf_module, app_name, namespace = includes for item in urlconf_module: if isinstance(item, RegexURLPattern): item.__class__ = DecoratedURLPattern item._decorate_with = func elif isinstance(item, RegexURLResolver): item.__class__ = DecoratedRegexURLResolver item._decorate_with = func return urlconf_module, app_name, namespace # urls.py - usage example with the admin site adminurls = include(admin.site.urls) urlpatterns = patterns('', # normal views (r'^assets/', include('myapp.assets.urls')), # all of these views are decoratored (r'^admin/', decorated_includes(superuser_required, include(admin.site.urls)) ), )