BLOG
Enjoy when you can, and endure when you must.
APR 25, 2013/Django
在include()上包装login_required()

在url.py里,我们可以利用include()包含其他的url.py进来,但这样默认不支持使用login_required再次包装,如下所示的代码:

    ...
    (r'^blog/', login_required(include('blog.urls'))),
)

会抛出异常。以下是一种解决方案(参考自StackOverflow):

    '''
    Used to require 1..n decorators in any view returned by a url tree
  
    Usage:
      urlpatterns = required(func,patterns(...))
      urlpatterns = required((func,func,func),patterns(...))
  
    Note:
      Use functools.partial to pass keyword params to the required 
      decorators. If you need to pass args you will have to write a 
      wrapper function.
  
    Example:
      from functools import partial
  
      urlpatterns = required(
          partial(login_required,login_url='/accounts/login/'),
          patterns(...)
      )
    '''
    if not hasattr(wrapping_functions,'__iter__'): 
        wrapping_functions = (wrapping_functions,)
  
    return [
        _wrap_instance__resolve(wrapping_functions,instance)
        for instance in patterns_rslt
    ]
  
def _wrap_instance__resolve(wrapping_functions,instance):
    if not hasattr(instance,'resolve'): return instance
    resolve = getattr(instance,'resolve')
  
    def _wrap_func_in_returned_resolver_match(*args,**kwargs):
        rslt = resolve(*args,**kwargs)
  
        if not hasattr(rslt,'func'):return rslt
        f = getattr(rslt,'func')
  
        for _f in reversed(wrapping_functions):
            # @decorate the function from inner to outter
            f = _f(f)
  
        setattr(rslt,'func',f)
  
        return rslt
  
    setattr(instance,'resolve',_wrap_func_in_returned_resolver_match)
  
    return instance

使用示例如下:

    # ...
)
  
urlpatterns += required(
    login_required,
    patterns('',
        (r'^blog/', include('blog.urls'))
    )
)
COMMENTS
LEAVE COMMNT