Задать вопрос

Тел: +7 965 3737 888





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.

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

Вопрос полезен? Да0/Нет0

Ответы (7):

Ответ полезен? Да0/Нет0

Aaand to fix it with Django 1.6, replace _get_url_patterns() with url_patterns

:) Oh the joys of maintenance.

Ответ полезен? Да0/Нет0

Thanks aehlke! :)

Ответ полезен? Да0/Нет0

This is broken in Django 1.3.

To fix it, replace the DecoratedURLPattern class with this:

class DecoratedURLPattern(RegexURLPattern):
    def resolve(self, *args, **kwargs):
        result = RegexURLPattern.resolve(self, *args, **kwargs)
        if result:
            result.func = self._decorate_with(result.func)
        return result

Ответ полезен? Да0/Нет0

This snippet works great, and allows you to enforce some precondition for a large number of URLs in one go (when using the fix from comment 3.).

If you add **kwargs to decorated_patterns, it also works with named patterns.

In my opinion, this is extremely useful, and the snippet is greatly underrated.

Thanks for sharing this!

Ответ полезен? Да0/Нет0

if you want to user included url files, like so

modify decorated_patterns to be:

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
        elif isinstance(p, RegexURLResolver):
            for pp in p._get_url_patterns():
                if isinstance(pp, RegexURLPattern):
                    pp.__class__ = DecoratedURLPattern
                    pp._decorate_with = func

return result

Ответ полезен? Да0/Нет0

@david_bgk: It would break reverse().

Sure, I could name the patterns, and I have considered doing that from time to time, but so far I am not yet sure if I want to.

Ответ полезен? Да0/Нет0

Why don't you use directly decorators in urls?

from foo.views import contact, imprint, add, edit

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