辞書のリストを使用して、任意のビューのアクセスルールを指定できるミドルウェアを作成しました。これらの辞書はそれぞれ次のようになります。
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'
誰でも許可する必要があります)。これはカスタムデコレータを使用して行うこともできますが、新しいチェックが必要になるとすぐに、新しいデコレータが必要になります。