8

現在、私の Django アプリには、「permission_required()」関数によって保護されている URL があります。

この関数は、3 つの異なる方法で呼び出されます。

  1. ハードコーディングされたパラメーターを使用して、views.py のデコレーターとして。
  2. カスタムクラスベースのジェネリックビューで、自動生成されたパラメーターを使用してプレーン関数として。
  3. ハードコーディングされたパラメーターを使用して、urls.py のビューを呼び出す関数として。

現在、アプリにメニュー システムを追加しています。ユーザーが各メニュー エントリの URL を要求する権限を持っているかどうかをメニュー エントリに反映させる必要があります。(上記のエントリをグレー表示するか、非表示にすることにより。)

URL を要求せずに、URL に必要なアクセス許可を照会する方法はありますか?

これまでに考えた唯一の解決策は、デコレーターをパラメーターのない「menu_permssion_required()」デコレーターに置き換え、すべてのアクセス許可を Python 構造にハードコーディングすることです。私のカスタム クラス ベースのジェネリック ビューは、必要なアクセス許可を既に自動生成しているため、これは後退しているように見えます。

現在のユーザーの URL パーミッションを反映するメニュー システムを作成する方法について何か提案はありますか?

4

3 に答える 3

2

問題を解決する方法の例を次に示します。

まず、permission_required の代わりに使用するデコレータ ラッパーを作成します。

from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
from django.core.exceptions import PermissionDenied
from functools import wraps
from  django.utils.decorators import available_attrs

def require_perms(*perms):
    def decorator(view_func):
        view_func.permissions = perms
        @wraps(view_func, assigned=available_attrs(view_func))
        def _wrapped_view(request, *args, **kwargs):
            for perm in perms:
                return view_func(request, *args, **kwargs)
            raise PermissionDenied()
        return _wrapped_view
    return decorator

次に、それを使用してビューを装飾します。

@require_perms('my_perm',)
def home(request):
.....

次に、メニュー項目に使用するタグを追加します。

from django.core.urlresolvers import resolve

def check_menu_permissions(menu_path, user):
    view = resolve(menu_path)
    if hasattr(view.func, "permissions"):
        permissions = view.func.permissions
        for perm in permissions:
            if user.has_perm(perm):
                return True # Yep, the user can access this url
            else:
                return False # Nope, the user cannot access this url
    return True #  or False - depending on what is the default behavior

最後に、テンプレートでメニュー ツリーを作成するときは、次のようにします。

<button href="{{ some_path }} {% if not check_menu_permissions some_path request.user %}disabled="disabled"{% endif %} />

注意: タグを使用して最後の部分をテストしていませんが、アイデアが得られたことを願っています。ここでの魔法は、デコレータの view_func にパーミッションを追加することです。そうすれば、resolve(path) を使用してこれにアクセスできます。これがパフォーマンスの面でどのように動作するかはわかりませんが、結局のところ、それは単なるアイデアです.

編集:例のバグを修正しました..

于 2012-06-10T19:59:59.183 に答える
2

URL を要求せずに、URL に必要なアクセス許可を照会する方法はありますか?

User.has_perm()およびUser.has_module_perms()

現在のユーザーの URL パーミッションを反映するメニュー システムを作成する方法について何か提案はありますか?

この質問は、django で Web サイトを作成するすべての人に関係するので、私は本当に好きです。私は自分でそれを経験し、2008 年に最初の django プロジェクトでメニュー「システム」をコーディングしました。完全に不必要な膨張。

したがって、リクエストのユーザー権限を尊重するメニュー「システム」を作成する方法について、私がサポートする提案はありません。

リクエストのユーザー権限を尊重するシンプルなメニューを作成する方法について提案があるので、それは完全に無関係ではないかもしれません.

  1. プレーンな HTMLでメニューを作成するだけで、生成する必要があるほど頻繁に変更されることはありません。これにより、Python コードもシンプルになります。

  2. に追加settings.TEMPLATE_CONTEXT_PROCESSORS:'django.core.context_processors.PermWrapper'

  3. {{ perms }} proxyUser.has_perms に使用します。

例:

{% if perms.auth %}
    <li class="divider"></li>

    {% if perms.auth.change_user %} 
    <li>
        <a href="{% url admin:auth_user_changelist %}">{% trans 'Users' %}</a>
    </li>
    {% endif %} 

    {% if perms.auth.change_group %} 
    <li>
        <a href="{% url admin:auth_group_changelist %}">{% trans 'User groups' %}</a>
    </li>
    {% endif %} 

{% endif %} 
{# etc, etc #}

それが私がナビゲーションをシンプルに、愚か、邪魔にならないようにしている方法です。また、ユーザーが詳細ページに簡単に移動できるように、メニューからそれほど遠くないところに常にオートコンプリートを含めています。だから、djangoプロジェクトでのナビゲーションについて私が知っているのはそれだけです.他の回答を読みたいです!

于 2012-06-10T19:15:07.300 に答える
1

同様の問題がありましたが、もう少し深くなりました。is_staffパーミッションだけでなく、蓋付きのユーザー (つまり、 、または)に基づく他のテストも必要user.units.count() > 1でした。ビューとテンプレートでこれらを複製すると、エラーが発生しやすいようです。

ビュー オブジェクトをイントロスペクトし、それをラップするすべてのデコレータを確認し、それらがチェックであるかどうかを調べることができます (私の場合: 最初の引数 Iuまたはuser)。すべて合格した場合は、リンクのレンダリングを許可します。

関数をラップするすべてのデコレータを取得すると、テクニックがもう少し詳しく説明されます。{% url %}これをDjango-menusの便利な代替品にまとめるアプリを見つけることができます。

于 2012-06-11T11:46:31.517 に答える