このページと次のページではここのコメントに対する権限について次の2つのケースを想定して設定します.
認証情報なし:全てのコメントについて閲覧のみ可能で,投稿・更新等は一切不可能.
認証情報あり:全てのコメントについて閲覧可能,新規投稿も可能.自身の投稿については更新・削除も可能.
認証情報なし:一切アクセス権限なし.
認証情報あり:新規投稿可能.自身が投稿したコメントについてのみ閲覧,更新,削除が可能.他のユーザの投稿コメントへのアクセス権限はなし.
このページでは Case #1 を想定した設定を行います.まず,comments アプリケーション内に permissions.py というファイルを作成し,このページのExample にあるような内容を記載します.具体的には,IsOwnerOrReadOnly
関数ではオブジェクトへのアクセスが GET などの安全なメソッドである場合には許可し,それ以外のメソッドについてはオブジェクトの所有者とログインユーザが一致する場合に許可をする設定を行なっています.
comments\permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Instance must have an attribute named `owner`.
return obj.owner == request.user
次に views.py を編集して,上で定義した IsOwnerOrReadOnly
と IsAuthenticatedOrReadOnly
を併用して目的の権限を実現します.
comments\views.py
from django.shortcuts import render
from rest_framework import generics
from rest_framework import permissions
from .models import Comment
from .serializers import CommentSerializer
from .paginations import LargeResultsSetPagination
from .permissions import IsOwnerOrReadOnly
# Create your views here.
class CommentList(generics.ListCreateAPIView):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
pagination_class = LargeResultsSetPagination
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
では実際に目的の権限を設定できているか確認します.まず認証情報を与えることなく全てのユーザのコメントを一覧で表示することができます.
...\django_comment_api>curl http://127.0.0.1:8000/comments/ ⏎ {"count":12,"next":"http://127.0.0.1:8000/comments/?page=2","previous":null,"results":[{"id":12,"owner_id":2,"title":"owner","body":"store owner_id","updated_at":"2023-11-23T17:28:50.507987"},{"id":11,"owner_id":1,"title":"owner","body":"store owner_id","updated_at":"2023-11-23T17:28:40.544771"}]}
コメントの詳細情報の閲覧も認証情報を与えることなく可能です.
...\django_comment_api>curl http://127.0.0.1:8000/comments/2/ ⏎ {"id":2,"owner_id":2,"title":"2個目のコメント","body":"コメントの本文2","updated_at":"2023-11-23T11:02:00"}
認証情報を与えなければ,新規投稿や編集は不可能です.
...\django_comment_api>curl -X POST -d "title=permission" -d "body=permissions" http://127.0.0.1:8000/comments/ ⏎ {"detail":"認証情報が含まれていません。"} ...\django_comment_api>curl -X PUT -d "title=edit" -d "body=body edit" http://127.0.0.1:8000/comments/1/ ⏎ {"detail":"認証情報が含まれていません。"}
次に,正しい認証情報を与えた場合も全てのユーザのコメントを一覧で表示することができます.
...\django_comment_api>curl -u user_a:password http://127.0.0.1:8000/comments/ ⏎ {"count":12,"next":"http://127.0.0.1:8000/comments/?page=2","previous":null,"results":[{"id":12,"owner_id":2,"title":"owner","body":"store owner_id","updated_at":"2023-11-23T17:28:50.507987"},{"id":11,"owner_id":1,"title":"owner","body":"store owner_id","updated_at":"2023-11-23T17:28:40.544771"}]}
もちろん自身で投稿したコメントの詳細情報は確認できます.
...\django_comment_api>curl -u user_a:password http://127.0.0.1:8000/comments/1/ ⏎ {"id":1,"owner_id":1,"title":"最初のコメント","body":"コメントの本文","updated_at":"2023-11-23T11:01:00"}
他のユーザが投稿したコメントも同様に詳細情報を確認できます.
...\django_comment_api>curl -u user_a:password http://127.0.0.1:8000/comments/2/ ⏎ {"id":2,"owner_id":2,"title":"2個目のコメント","body":"コメントの本文2","updated_at":"2023-11-23T11:02:00"}
認証情報を与えると新規の投稿が可能で,投稿されたコメントには自身の owner_id がセットされます.
...\django_comment_api>curl -X POST -d "title=permission" -d "body=permissions" -u user_a:password http://127.0.0.1:8000/comments/ ⏎ {"id":13,"owner_id":1,"title":"permission","body":"permissions","updated_at":"2023-11-23T17:41:38.364189"}
自分自身が投稿したコメントは更新(あるいは削除も)することが可能です.
...\django_comment_api>curl -X PUT -d "title=edit" -d "body=body edit" -u user_a:password http://127.0.0.1:8000/comments/1/ ⏎ {"id":1,"owner_id":1,"title":"edit","body":"body edit","updated_at":"2023-11-23T17:42:58.795269"}
他のユーザが投稿したコメントを更新する権限はありません.
...\django_comment_api>curl -X PUT -d "title=edit" -d "body=body edit" -u user_a:password http://127.0.0.1:8000/comments/2/ ⏎
{"detail":"このアクションを実行する権限がありません。"}
...\django_comment_api>