get from http://127.0.0.1:8000/api/album_list/, response credential not provided
post to http://127.0.0.1:8000/api/api-token-auth/ with login, obtain token
get request to http://127.0.0.1:8000/api/album_list/ with token, server responds with data
send put request to http://127.0.0.1:8000/api/album_detail/38/ to edit chuanshuo's post but with bob's token
server responds permission denied
post request to http://127.0.0.1:8000/api/api-token-auth/ with chuanshuo's login
obtain chanshuo's token
send put request to http://127.0.0.1:8000/api/album_detail/38/ with chuanshuo's token to edit his own post, successful
#settings
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
]
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
]
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES':(
'rest_framework.permissions.IsAuthenticated',
),
}
#powershell
python manage.py migrate
------------------------------
#music/api/urls
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from music.api import apiview, mixins
from rest_framework.authtoken import views
app_name = 'musicAPI'
urlpatterns = [
path('album_list/', apiview.AlbumList.as_view(), name='AlbumList'),
path('album_detail/<int:pk>/', apiview.AlbumDetail.as_view(), name='AlbumDetail'),
path('album_list_mixin/', mixins.AlbumListMixin.as_view(), name='AlbumListMixin'),
path('album_detail_mixin/<int:pk>/', mixins.AlbumDetailMixin.as_view(), name='AlbumDetailMixin'),
path('api-token-auth/', views.obtain_auth_token, name='AuthToken'),
]
urlpatterns = format_suffix_patterns(urlpatterns)
-----------------------------------------------------
#music/api/apiview
from music.models import Album
from music.api.serializers import MusicSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
class AlbumList(APIView):
def get(self, request, format=None):
albums = Album.objects.all()
serializer = MusicSerializer(albums, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = MusicSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class AlbumDetail(APIView):
def get_object(self, pk):
try:
return Album.objects.get(pk=pk)
except Album.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
album = self.get_object(pk)
serializer = MusicSerializer(album)
return Response(serializer.data)
def put(self, request, pk, format=None):
album = self.get_object(pk)
#only owner can edit
if album.author != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status= status.HTTP_403_FORBIDDEN)
serializer = MusicSerializer(album, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
album = self.get_object(pk)
# only owner can delete
if album.author != request.user:
return Response({"detail": "You do not have permission to perform this action."},
status=status.HTTP_403_FORBIDDEN)
album.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
-----------------------------------------
#music/api/mixins
from music.models import Album
from music.api.serializers import MusicSerializer
from rest_framework import mixins, generics, permissions
from .permissions import IsOwnerOrReadOnly
class AlbumListMixin(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Album.objects.all()
serializer_class = MusicSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class AlbumDetailMixin(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Album.objects.all()
serializer_class = MusicSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
------------------------------------
#music/api/permisions
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""
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
# Write permissions are only allowed to the owner of the snippet.
return obj.author == request.user
reference:
https://www.youtube.com/watch?v=PFcnQbOfbUU&list=PLbpAWbHbi5rMV3H0S5IDK3cSRC1Jas3VP&index=3
https://stackoverflow.com/questions/39923384/str-object-is-not-callable-django-rest-framework
https://stackoverflow.com/questions/53649252/django-rest-framework-basepermissionmetaclass-object-is-not-iterable
http://chuanshuoge2.blogspot.com/2019/05/django-37-rest-framework-class-based.html
http://chuanshuoge2.blogspot.com/2019/05/django-36-rest-framework-class-based.html
No comments:
Post a Comment