21

djangoで行レベルのパーミッションを行う方法はありますか? 私はそうではないと思っていましたが、ドキュメントでこれに気づきました:

アクセス許可は、オブジェクトのタイプごとだけでなく、特定のオブジェクト インスタンスごとにも設定できます。ModelAdmin クラスが提供する has_add_permission()、has_change_permission()、および has_delete_permission() メソッドを使用すると、同じタイプの異なるオブジェクト インスタンスの権限をカスタマイズできます。

https://docs.djangoproject.com/en/dev/topics/auth/

しかし、インスタンスごとのアクセス許可を実際に実装する方法に関するドキュメントはありません

4

5 に答える 5

27

私が構築しているアプリケーションでは、単純なデコレーターを介して行レベルのアクセス許可を提供したいと考えています。これができるのは、request.user がモデル オブジェクトの所有者であるかどうかだけが条件だからです。

以下はうまくいくようです:

from functools import wraps
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist

def is_owner_permission_required(model, pk_name='pk'):
    def decorator(view_func):
        def wrap(request, *args, **kwargs):
            pk = kwargs.get(pk_name, None)
            if pk is None:
                raise RuntimeError('decorator requires pk argument to be set (got {} instead)'.format(kwargs))
            is_owner_func = getattr(model, 'is_owner', None)
            if is_owner_func is None:
                raise RuntimeError('decorator requires model {} to provide is_owner function)'.format(model))
            o=model.objects.get(pk=pk) #raises ObjectDoesNotExist
            if o.is_owner(request.user):
                return view_func(request, *args, **kwargs)
            else:
                raise PermissionDenied
        return wraps(view_func)(wrap)
    return decorator

景色:

@login_required
@is_owner_permission_required(Comment)
def edit_comment(request, pk):
    ...

URL:

url(r'^comment/(?P<pk>\d+)/edit/$', 'edit_comment'),

モデル:

class Comment(models.Model):
    user = models.ForeignKey(User, ...
    <...>
    def is_owner(self, user):
        return self.user == user

フィードバックやコメントをお待ちしております。

ポール・ボーマンズ

于 2012-12-02T17:48:53.123 に答える
7

ドキュメントで説明されているメソッドを使用すると、管理者の特定のオブジェクトへのアクセスを制限できます。True各メソッドにはプレイ中のオブジェクトが渡されます。これを使用して、またはを返すことで、ユーザーがアクセスできるかどうかを判断できますFalse

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_add_permission(self, request):
        # This one doesn't get an object to play with, because there is no
        # object yet, but you can still do things like:
        return request.user.is_superuser
        # This will allow only superusers to add new objects of this type

    def has_change_permission(self, request, obj=None):
        # Here you have the object, but this is only really useful if it has
        # ownership info on it, such as a `user` FK
        if obj is not None:
            return request.user.is_superuser or \
                   obj.user == request.user
            # Now only the "owner" or a superuser will be able to edit this object
        else:
            # obj == None when you're on the changelist page, so returning `False`
            # here will make the changelist page not even viewable, as a result,
            # you'd want to do something like:
            return request.user.is_superuser or \
                   self.model._default_manager.filter(user=request.user).exists()
            # Then, users must "own" *something* or be a superuser or they
            # can't see the changelist

    def has_delete_permission(self, request, obj=None):
        # This pretty much works the same as `has_change_permission` only
        # the obj == None condition here affects the ability to use the
        # "delete selected" action on the changelist
于 2012-08-09T21:10:47.723 に答える
7

配管があります(これは、リンクした同じページの下部からのものです):

オブジェクト権限の処理

Django のパーミッション フレームワークにはオブジェクト パーミッションの基盤がありますが、コアにはその実装はありません。つまり、オブジェクトのアクセス許可をチェックすると、常に False または空のリストが返されます (実行されたチェックによって異なります)。認証バックエンドは、各オブジェクト関連の認証方法のキーワード パラメーター obj および user_obj を受け取り、必要に応じてオブジェクト レベルのアクセス許可を返すことができます。

ただし、デフォルトの実装は提供されていません。これはよくある話題なので; SOにはたくさんの答えがあります。右側を確認すると、いくつかのリストが表示されます。

基本的なアイデアは、django パッケージのパーマ グリッドを参照し、オブジェクト レベルのパーミッションの実装を選択することです。個人的にはdjango-guardianが好きです。

于 2012-08-09T20:47:02.903 に答える
0

PyPi で利用できるdjango 用の「パーミッション」アプリは多数あります
。たとえば、django-object-permission を見ることができます。

ドキュメントが参照しているのは、パーミッションを実装する機能があるということです。そして、人々はこのためのアプリを作成することで、まさにそれを実現しました。

于 2012-08-09T20:46:10.817 に答える