私はDjango + Django Rest-frameworkを使用した開発の初心者であり、REST APIアクセスを提供するプロジェクトに取り組んでいます。特定のApiViewまたはViewsetの各アクションに異なる権限を割り当てるためのベストプラクティスは何なのかと思っていました。
'IsAdmin'、 'IsRole1'、 'IsRole2'、...などのいくつかのアクセス許可クラスを定義し、さまざまなアクセス許可を単一のアクション(たとえば、Role1のユーザーが作成または取得できるユーザー、 Role2は更新でき、管理者のみが削除できます)。
許可クラスを「作成」、「リスト」、「取得」、「更新」、「削除」アクションに割り当てるために、クラスベースのビューをどのように構成できますか?同じ許可パターンを持つ異なるテーブルで再利用できるクラスを作成するためにそうしています。
たぶん私は水のインチで溺れているだけです、あなたの返事をありがとう。
カスタム権限クラス DRFのBasePermission
を作成できます。
has_permission
は、request
およびview
オブジェクトにアクセスできる場所に実装します。 request.user
で適切な役割を確認し、必要に応じてTrue
/False
を返すことができます。
提供されている IsAuthenticatedOrReadOnly クラス(および他のクラス)を見て、それがいかに簡単であるかを確認してください。
お役に立てば幸いです。
DRFドキュメントでは、
注:インスタンスレベルのhas_object_permissionメソッドは、ビューレベルのhas_permissionチェックがすでに合格している場合にのみ呼び出されます
user
オブジェクトに関する以下の許可を想定してみましょう
permissons.py
_from rest_framework import permissions
class UserPermission(permissions.BasePermission):
def has_permission(self, request, view):
if view.action == 'list':
return request.user.is_authenticated() and request.user.is_admin
Elif view.action == 'create':
return True
Elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
return True
else:
return False
def has_object_permission(self, request, view, obj):
# Deny actions on objects if the user is not authenticated
if not request.user.is_authenticated():
return False
if view.action == 'retrieve':
return obj == request.user or request.user.is_admin
Elif view.action in ['update', 'partial_update']:
return obj == request.user or request.user.is_admin
Elif view.action == 'destroy':
return request.user.is_admin
else:
return False
_
views.py
_from .models import User
from .permissions import UserPermission
from .serializers import UserSerializer
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (UserPermission,)
_
[〜#〜]編集[〜#〜]
Django 2.0の場合、is_authenticated()
を_is_authenticated
_で置き換えます。メソッドは属性に変更されました。
私は個人的にこの種のfrankenmonsterカスタムアクセス許可を嫌っています。私の意見では、Djangoフレームワークになると、それはあまり慣用的ではないので、次の解決策を思いつきました-@list_route
および@detail_route
デコレーターが機能します。メソッド/関数がファーストクラスオブジェクトであるという事実に依存しています
まず、そのようなデコレータを作成しています:
decorators.py
def route_action_arguments(**kwargs):
"""
Add arguments to the action method
"""
def decorator(func):
func.route_action_kwargs = kwargs
return func
return decorator
ご覧のとおり、関数に辞書を追加し、引数リストとして渡されたパラメーターで修飾します
今、私はそのようなミックスインを作成しました:mixins.py
class RouteActionArgumentsMixin (object):
"""
Use action specific parameters to
provide:
- serializer
- permissions
"""
def _get_kwargs(self):
action = getattr(self, 'action')
if not action:
raise AttributeError
print('getting route kwargs for action:' + action)
action_method = getattr(self, action)
kwargs = getattr(action_method, 'route_action_kwargs')
print(dir(kwargs))
return kwargs
def get_serializer_class(self):
try:
kwargs = self._get_kwargs()
return kwargs['serializer']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_serializer_class()
def get_permissions(self):
try:
kwargs = self._get_kwargs()
return kwargs['permission_classes']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_permissions()
Mixinは2つのことを行います。 get_permissions
が呼び出されると、実行された「アクション」を確認し、route_action_kwargs
に関連付けられているviewset.action_method.route_action_kwargs
からpermission_classesコレクションを検索します
get_serializer_class
が呼び出されると、同じことが行われ、route_action_kwargs
からserializer
が選択されます
それを使用する方法:
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
"""
User and profile managment viewset
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@list_route(methods=['post'])
@route_action_arguments(permission_classes=(AllowAny,), serializer=LoginSerializer)
def login(self, request):
serializer = self.get_serializer_class()(data=request.data)
カスタムルートの場合、明示的に定義することで、メソッドに@route_action_arguments
を明示的に設定できます。
一般的なビューセットとメソッドに関しては、@method_decorator
を使用して追加できます
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
Djangoには、認証バックエンドとしてDjango Guardianを使用するDjangoObjectPermissionsというパーミッションクラスがあります。
設定でDjangoガーディアンをアクティブにすると、ビューにpermission_classes = [DjandoObjectPermissions]
を追加するだけで、自動的に権限認証が行われるため、特定の権限セットに基づいて「CRUD」することができますDjango.contrib.auth
グループまたはユーザー。
Gist の例を参照してください。
Django Guardianを認証の裏付けとして設定できます http://Django-guardian.readthedocs.org/en/latest/installation.html
RestFrameworkのクラスベースのビューには、HTTP動詞ごとにメソッドがあります(つまり、HTTP GET => view.get()など)。ドキュメントにあるように、Django.contrib.authの権限、ユーザー、グループ、およびデコレータを使用するだけです。