2012-08-08 3 views
16

私はDjangoのuser_passes_testデコレータを使用してユーザ権限をチェックしています。user_passes_testデコレータコール関数でDjangoリクエストオブジェクトを渡す方法

@user_passes_test(lambda u: has_add_permission(u, "project")) 
def create_project(request): 
...... 

私は2つの引数ユーザーや文字列を受け取り、コールバック関数has_add_permissionを呼び出しています。リクエストオブジェクトをそれに沿って渡したいと思いますか?また、デコレータ内のUserオブジェクトに直接アクセスする方法を教えてください。

+0

私は不思議です、どうしてこれについてどうしましたか?あなたは自分のデコレータを書いていましたか? – teewuane

+0

デコレータを使用する代わりに、ビューコード自体の内部で権限をチェックしています。それは私にビューロジックをより良くコントロールさせました。 –

+0

これも私がやったことです。ありがとう! – teewuane

答えて

12

いいえ、user_passes_testにリクエストを渡すことはできません。なぜ、どのようにそれが動作だけsourceに頭の上、理解するために:

def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 
    """ 
    Decorator for views that checks that the user passes the given test, 
    redirecting to the log-in page if necessary. The test should be a callable 
    that takes the user object and returns True if the user passes. 
    """ 

    def decorator(view_func): 
     @wraps(view_func, assigned=available_attrs(view_func)) 
     def _wrapped_view(request, *args, **kwargs): 
      if test_func(request.user): 
       return view_func(request, *args, **kwargs) 
      path = request.build_absolute_uri() 
      # If the login url is the same scheme and net location then just 
      # use the path as the "next" url. 
      login_scheme, login_netloc = urlparse.urlparse(login_url or 
                 settings.LOGIN_URL)[:2] 
      current_scheme, current_netloc = urlparse.urlparse(path)[:2] 
      if ((not login_scheme or login_scheme == current_scheme) and 
       (not login_netloc or login_netloc == current_netloc)): 
       path = request.get_full_path() 
      from django.contrib.auth.views import redirect_to_login 
      return redirect_to_login(path, login_url, redirect_field_name) 
     return _wrapped_view 
    return decorator 

これはuser_passes_testデコレータの背後にあるコードです。ご覧のように、デコレータ(あなたの場合はlambda u: has_add_permission(u, "project"))に渡されたテスト関数は、ただ1つの引数、request.userを渡します。今度はrequest自体を渡すために独自のデコレータを書くこともできますが、デフォルトのuser_passes_testの実装ではできません。

+0

Chrisに感謝します。私は新しいデコレータを書かなければならないか、ビューコードの中でそれを行うかのどちらかと思います。 –

4

request.userではなく、requestで修飾された機能を使用するように編集すると、user_passes_testが見つかりました。私は、ビューのデコレータデコレータについてthis blog postで短いバージョンを持っていますが、後世のために、ここに私の完全な編集されたコードです:

def request_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 
    """ 
    Decorator for views that checks that the request passes the given test, 
    redirecting to the log-in page if necessary. The test should be a callable 
    that takes the request object and returns True if the request passes. 
    """ 

    def decorator(view_func): 
     @wraps(view_func, assigned=available_attrs(view_func)) 
     def _wrapped_view(request, *args, **kwargs): 
      if test_func(request): 
       return view_func(request, *args, **kwargs) 
      path = request.build_absolute_uri() 
      # urlparse chokes on lazy objects in Python 3, force to str 
      resolved_login_url = force_str(
       resolve_url(login_url or settings.LOGIN_URL)) 
      # If the login url is the same scheme and net location then just 
      # use the path as the "next" url. 
      login_scheme, login_netloc = urlparse(resolved_login_url)[:2] 
      current_scheme, current_netloc = urlparse(path)[:2] 
      if ((not login_scheme or login_scheme == current_scheme) and 
        (not login_netloc or login_netloc == current_netloc)): 
       path = request.get_full_path() 
      from django.contrib.auth.views import redirect_to_login 
      return redirect_to_login(
       path, resolved_login_url, redirect_field_name) 
     return _wrapped_view 
    return decorator 

はかなり私がやった唯一の事は if test_func(request):に変更 if test_func(request.user):ました。

7

Django 1.9は、UserPassesTestMixinを導入しました。これは、テスト機能としてtest_funcを使用しています。つまり、リクエストはself.requestで利用可能です。したがって、次のようなことができます。

class MyView(UserPassesTestMixin, View): 
    def test_func(self): 
     return has_add_permission(self.request.user, self.request) 

ただし、これはクラスベースのビューでのみ機能します。

関連する問題