Django REST Frameworkに再挑戦 その5
概要
Django REST Frameworkに再挑戦 その5
参考サイト
www.codingforentrepreneurs.com
Custom Permissions
- api/views.pyに、permissionのメソッドを追加する。めっちゃあるな!
公式サイト permissions:
Permissions - Django REST framework
from rest_framework.permissions import ( AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, )
- createAPIviewで試してみる。
class PostCreateAPIView(CreateAPIView): queryset = Post.objects.all() serializer_class = PostCreateUpdateSerializer permission_classes = [IsAuthenticated] def perform_create(self, serializer): serializer.save(user=self.request.user, title='my title')
ゲストウィンドウなどで、ログインしてない状態でcreateviewを開いてみる。
"detail": "Authentication credentials were not provided."
と表示されていればOK!adminuserのみにしたい場合は、以下のように設定する。
IsAdminUser
を追記するだけ。
class PostCreateAPIView(CreateAPIView): queryset = Post.objects.all() serializer_class = PostCreateUpdateSerializer permission_classes = [IsAuthenticated, IsAdminUser]
- UpdateViewにも同様に、permissionをつける。
class PostUpdateAPIView(RetrieveUpdateAPIView): queryset = Post.objects.all() serializer_class = PostCreateUpdateSerializer lookup_field = 'slug' permission_classes = [IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save(user=self.request.user)
- userが投稿したpostのみを表示する。そのためにまずは、api/permissions.pyを作成して、カスタムしたpermissionのclassを作成する。
公式サイト:custom permission:
Permissions - Django REST framework
from rest_framework.permissions import BasePermission class IsOwnerOrReadOnly(BasePermission): message = 'You must be the owner of this object.' def has_object_permission(self, request, view, obj): return obj.user == request.user # True or Falseを返す
- 上記のIsOwnerOrReadOnly classを、他のpermission classと同じように指定する。これでuserがオーナーの記事しか編集できなくなる。(readは可能)
class PostUpdateAPIView(RetrieveUpdateAPIView): queryset = Post.objects.all() serializer_class = PostCreateUpdateSerializer lookup_field = 'slug' permission_classes = [IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
- 公式サイトから、SAFE_METHODSを使ったpermissionを追記してみる。編集するのは、permissions.py。
class IsOwnerOrReadOnly(BasePermission): message = 'You must be the owner of this object.' def has_object_permission(self, request, view, obj): my_safe_method = ['PUT'] if request.method in my_safe_method:#もしくは、if request.method in permissions.SAFE_METHODS: return True return obj.user == request.user # True or Falseを返す
- さらに修正してみる。
class IsOwnerOrReadOnly(BasePermission): message = 'You must be the owner of this object.' my_safe_method = ['PUT'] # 2つとも同じ意味。。。なはず。request.methodのなかに、'PUT'がある場合は、Trueを返すという関数 def has_permission(self, request, view): if request.method in self.my_safe_method: return True return False def has_object_permission(self, request, view, obj): if request.method in self.my_safe_method: return True return obj.user == request.user
- SAFE_METHOD は、上記の
my_safe_method
と同じ意味のもの?そのため、SAFE_METHODをimportして利用すると以下のようになる。permissions.pyを編集する。
def has_object_permission(self, request, view, obj): if request.method in SAFE_METHODS: return True return obj.user == request.user # True or Falseを返す
- ただし、このままでは、エラーが出て表示されない。my_safe_method に、
GET
も追加する。最終的にここでは以下のように設定する。
from rest_framework.permissions import BasePermission, SAFE_METHODS class IsOwnerOrReadOnly(BasePermission): message = 'You must be the owner of this object.' my_safe_method = ['GET','PUT'] def has_permission(self, request, view): if request.method in self.my_safe_method: return True return False def has_object_permission(self, request, view, obj): #member = Membership.objects.get(user=request.user) #member.is_active if request.method in SAFE_METHODS: return True return obj.user == request.user # True or Falseを返す
- Custom Permisionはよくわからなかったので、公式サイトの重要と思われる箇所を読んでみる。
To implement a custom permission, override BasePermission and implement either, or both, of the following methods: # カスタムパーミッションを実装するには、BasePermissionと以下のメソッドのどちらか、もしくは両方を上書きする必要がある。 .has_permission(self, request, view) .has_object_permission(self, request, view, obj) The methods should return True if the request should be granted access, and False otherwise. # この2つのメソッドは、権限のあるアカウントからのアクセス(のrequest)の場合は、Trueが返されて、そうでない場合はFalseを返す。 If you need to test if a request is a read operation or a write operation, you should check the request method against the constant SAFE_METHODS, which is a tuple containing 'GET', 'OPTIONS' and 'HEAD'. For example: # requestが読み込みか書き込みかをテストする必要がある場合は、GET OPTIONS HEADを含む既定の'SAFE_METHODS'を使って、さらに細かく分岐を行いチェックすることができる。例えば以下のような感じ if request.method in permissions.SAFE_METHODS: # Check permissions for read-only request else: # Check permissions for write request Note: The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call .check_object_permissions(request, obj). If you are using the generic views then this will be handled for you by default. # has_object_permissionメソッドの方は、has_permissionをpassした時だけ呼び出される。 # the instance-levelのchecksをするためには、view codeは、.check_object_permissions(request, obj)を呼び出す必要がある。 # もしgeneric viewsを使ってたら、デフォルトでハンドルされるよ。
うーん、翻訳してもよくわからんw