Decorating urlpatterns

One thing I wanted for a while was the ability to basically apply something like @login_required to a bunch of urlpatterns in one go, instead of having to decorate each and every view manually. I finally spent some time looking through the Django source, and I came up with the following:

from django.core.urlresolvers import RegexURLPattern
from django.conf.urls.defaults import patterns

class DecoratedURLPattern(RegexURLPattern):
    def resolve(self, *args, **kwargs):
        result = RegexURLPattern.resolve(self, *args, **kwargs)
        if result:
            result = list(result)
            result[0] = self._decorate_with(result[0])
        return result

def decorated_patterns(prefix, func, *args):
    result = patterns(prefix, *args)
    if func:
        for p in result:
            if isinstance(p, RegexURLPattern):
                p.__class__ = DecoratedURLPattern
                p._decorate_with = func
    return result

def control_access(view_func):
    def _checklogin(request, *args, **kwargs):
        raise Http404()
    return _checklogin

urlpatterns = patterns('views',
    # unprotected views
    (r'^public/contact/$',      'contact'),
    (r'^public/imprint/$',        'imprint'),
) + decorated_patterns('views', control_access,
    (r'^admin/add/$',      'add'),
    (r'^admin/edit/$',      'edit'),
)

In this example, the latter two views will always raise a 404.

So far it seems to work quite nicely.

5 thoughts on “Decorating urlpatterns

  1. I did actually. It’s a good idea, and for some reason I hadn’t even thought about approaching it like that. Although in my case, it would break the ability to use reverse() without explicitly naming the patterns, which is something I am relying on for now.

    Of course if you’re using generic views, then that won’t be an issue.

    Like

  2. I think you’re doing it right. The only mistake I can see right now is that you’re checking twice for RegexURLPattern:

    “if isinstance(p, RegexURLPattern)“ instead of “if isinstance(p, RegexURLResolver)“

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s