LoginSignup
4
3

More than 5 years have passed since last update.

Pyramid の独自 View Decorator で view 関数の前後に処理を挿入する

Last updated at Posted at 2015-01-09

[2015/3/20 色々調べて分かった内容にアップデート。なんか別物になった]

ユーザ認証あり & 認証済みページではどの画面でもヘッダ部分にユーザ名を表示、みたいなありがちな Web アプリを作るときの定形処理を自動化。

  • 認証済みで user という permission を持っているときだけ view の実行が許可されるような view_decorator を定義する
    • 同様に admin という permission でだけ view の実行ができるようにする
  • request.user へのアクセスで User オブジェクトにアクセスする
    • 最初にアクセスしたときにだけ、SQL を実行して models.User を検索
def permission_view_config(permission):
    def pvc(**params):
        settings = dict(permission=permission, _depth=1)
        settings.update(params)

        def wrapped_view_config(original_func):
            return view_config(**settings)(original_func)
        return wrapped_view_config
    return pvc


user_view_config = permission_view_config('user')
admin_view_config = permission_view_config('admin')
__init__.py
def groupfinder(user_code, request):
    if not request.user:
        return []
    elif request.user.is_admin:
        return ['group:users', 'group:admin']
    else:
        return ['group:users']


def get_user(request):
    user_id = unauthenticated_userid(request)
    if user_id is not None:
        return DBSession.query(User).get(user_id)


class RootFactory(object):
    __acl__ = [
        (Allow, 'group:users', 'user'),
        (Allow, 'group:admin', 'admin')
    ]

    def __init__(self, request):
        pass


def main(global_config, **settings):
    # ...
    config = Configurator(settings=settings, root_factory='.RootFactory')

    # request の user プロパティにアクセスしたら get_user してね、という指定。これ重要。
    config.set_request_property(get_user, 'user', reify=True)

    authn_policy = AuthTktAuthenticationPolicy('...', callback=groupfinder, hashalg='sha512')
    authz_policy = ACLAuthorizationPolicy()
    config.set_authentication_policy(authn_policy)
    config.set_authorization_policy(authz_policy)
    # ...

こんな風に使えば

views.py
@user_view_config(route_name='index', renderer='templates/index.jinja2')
def index(request):
    # ここは user の permission を持っている人だけ
    do_something_with(request.user)  # user が使える
    return {'name': 'my_app'}

@admin_view_config(route_name='index', renderer='templates/add_user.jinja2')
def add_user(request):
    # ここは admin の permission を持っている人だけ
    do_something_with(request.user)  # user が使える
    return {'name': 'my_app'}

inspired by Pyramid でカスタムの View Decorator を実装する

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3