django login_required includeに追加

4146 ワード

参照先:https://codeday.me/bug/20171128/102555.html
djangoプロジェクトを書くとき、私の習慣は最後に権限制御を書くことで、最も簡単なのはloginを書くことです.requiredです.通常は各views関数に飾りを1つずつ付けます.
@login_required
def index(request):
    pass 

もっとまじめにurlにロゴを付けるrequired.
urlpatterns = [
    path('user/', login_required(user_manage), name="account_users_index"),
     path('user/', login_required()(UserList.as_view()), name='account_users_list'),
]

しかし、ルートがもう少し多ければ、追加の作業量はまだ大きい.修正するなら、もっと面倒です.
解決策が来た.必要なところに一度だけ追加することです.すべて追加します.
#!/bin/env python
# -*- coding:utf-8 -*-

def required(wrapping_functions, patterns_rslt):
    '''
    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_base = [
    path('', index_view),
]
urlpatterns = required(
    login_required,
    urlpatterns_base
)

urlpatterns += [
    path('login', include(zjxl_sso.get_login_urls())),
]