Login

Decorating URL includes

Author:
cotton
Posted:
August 25, 2011
Language:
Python
Version:
1.3
Tags:
urls urlconf decorator urlpatterns resolve
Score:
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)) ),
)

More like this

  1. Generic object_detail view with multiple named URL filters by cotton 3 years, 2 months ago
  2. @url decorator - getting rid of urlpatterns by southern_sun 7 years, 6 months ago
  3. Resolve URLs to view name and args/kwargs by fahhem 4 years, 3 months ago
  4. SSL Middleware by sjzabel 7 years, 12 months ago
  5. Decorating urlpatterns by miracle2k 7 years, 2 months ago

Comments

s29 (on October 26, 2011):

awesome, thanks!

#

Please login first before commenting.