0

辞書のリストを使用して、任意のビューのアクセスルールを指定できるミドルウェアを作成しました。これらの辞書はそれぞれ次のようになります。

REQUIREMENTS=(
    {'viewname':'addtag',
     'permissions':'can_add_tags'},
    {'regex':re.compile(r'^somestart'),
    'user_check':lambda request:request.user.username=='sam'}
)

次に、ミドルウェアで、これらの要件のどれが現在の要求に一致するかを調べようとします。これを行うには、完全な要件をフィルタリングし、フィルター関数でこのコードを使用して、パスが一致するかどうかを確認します。

def process_request(self,request):

    def path_matches(self,req):
        path_matches = False

        if  (req.has_key('url') and req['url'] == request.path ) or\
            (req.has_key('regex') and req['regex'].search(request.path)) or\
            (req.has_key('viewname') and resolve(request.path).url_name==req['viewname']):
            path_matches=True

        return path_matches

    requirements = filter(path_matches,REQUIREMENTS)
    # now use the returned requirements to determine if a user
    # matches the requirement and

今の私の質問は、チェックをどの順序で使用する必要があるかということです。URLのチェックが最速であることは明らかなので、これを最初に行う必要があります。しかし、問題は、正規表現検索またはdjangoのURL解決機能を最初に実行する必要があるかどうかです。

現在、パフォーマンスの問題はないので、これは学術的な問題です。そして、誰かがこれを解決するためのすべてのより良い解決策を持っているならば、それはさらに良いでしょう。


編集:

与えられた答えに反応するために:私がやろうとしていることは、単一のファイルで複数の外部アプリの表示を制限する可能性を作成することです。したがって、デコレータは、次のようなことをしたくない限り、オプションではありません。

from ext_app1 import view1,view2
from ext_app2 import view3

@permission_required('can_do_stuff')
def view1_ext(*args,**kwargs):
    return view1(args,kwargs)

これにより、権限を変更するたびにURL仕様が書き換えられます。それは避けたい。さらに、私のソリューションでは、user_check関数で次のようなユーザーのチェックを行うことができます。

def check_user(user):
    if len(Item.objects.get(creator=user,datetime=today)) > 3:
        return False
    return True

これは、ユーザーが1日にアップロードできるアイテムの数を制限する簡単な方法です。(わかりました、それはuser_passes_testでも可能です)。

もう1つは、リクエストがPOSTである場合、またはリクエストに特定のキーと値のペアが含まれている場合にのみ、権限を確認したい場合があります('action':'delete'たとえば、権限が必要ですが、'action':'change'誰でも許可する必要があります)。これはカスタムデコレータを使用して行うこともできますが、新しいチェックが必要になるとすぐに、新しいデコレータが必要になります。

4

2 に答える 2

1

user_passes_test デコレータを探しているかもしれません。

ミドルウェアを使用する代わりに、必要なビューを装飾できます。

コードは次のようになります。

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda user: user.has_perm('model.can_add_tags') \
                                and user.username == 'sam')
def my_view(request):
    ...  
于 2012-05-24T18:46:25.800 に答える
1

Django の組み込みのユーザー認証およびパーミッション システム( django.contrib.auth) を使用している場合は、ミドルウェアの代わりに Django が提供するビュー デコレータの使用を検討する必要があります。これらにはいくつかの利点があります。

  • 一緒に変更されるコードは同じ場所にあります。つまり、ビューのコードを変更するときは、他のパーミッションを変更するときよりも、特定のビューのパーミッションを変更する必要がある可能性が高くなります。
  • コードの大部分を自分で記述する必要がないため、プロジェクトが小さくなり、保守が容易になります。

単純な状況ではlogin_requiredpermission_requiredデコレータを使用できます。より複雑な条件では、user_passes_testデコレータを使用して、指定したい条件にユーザーが合格したかどうかを確認できます。

ビュー関数のコードは次のようになります (例はドキュメントから引用されています)。

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...

クラスベースのビューを使用している場合は、少し異なります (この例もドキュメントから引用されています)。

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(ProtectedView, self).dispatch(*args, **kwargs)

Django のパーミッション システムを使用しない正当な理由がある場合でも、同様のアプローチを採用できます。デコレーターコードはdjango.contrib.auth、独自のデコレーターの基礎として簡単に使用できます。

于 2012-05-24T19:08:20.060 に答える