Добавьте механизм аутентификации при помощи обычного токена в проект Yatube API, реализованный на view-функциях.
Сделайте так, чтобы при создании нового поста через POST-запрос в поле author автоматически записывался объект автора по токену.Вам нужно:
- Сделать доступ к API только после авторизации; опишите эндпоинт, по которому можно будет получать токен.
- В сериализаторе настроить поле
author
в режим «только для чтения». - При создании публикации в качестве автора указывать пользователя, полученного из объекта
request.user
. - Разрешить изменение или удаление постов только авторам этих постов, в противном случае возвращать статус 403.
Подсказка:
Вам нужно добавить пару строчек кода в urls.py, одну строчку в serializers.py и сделать изменение в файле views.py.
В сериализаторе переключить поле в режим работы только для чтения можно несколькими способами. Поле можно переопределить и указать опциональный параметр read_only=True
.
Например: <имя поля> = serializers.PrimaryKeyRelatedField(read_only=True)
. Другой вариант: указать дополнительный параметр read_only_fields
во внутреннем классе Meta и перечислить в нем все поля, которые должны работать в режиме только для чтения.
Объект пользователя, сделавшего запрос, хранится в объекте request
. Запишите объект автора в соответствующее поле при создании объекта.
Код serializers.py:
from rest_framework import serializers from .models import Post class PostSerializer(serializers.ModelSerializer): class Meta: fields = ('id', 'text', 'author', 'image', 'pub_date') # укажите поля, доступные только для чтения read_only_fields = ('author',) model = Post
Код views.py:
from django.shortcuts import get_object_or_404 from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status from .models import Post from .serializers import PostSerializer @api_view(['GET', 'POST']) def api_posts(request): if request.method == 'POST': serializer = PostSerializer(data=request.data) if serializer.is_valid(): serializer.save(author=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) posts = Post.objects.all() serializer = PostSerializer(posts, many=True) return Response(serializer.data) @api_view(['GET', 'PUT', 'PATCH', 'DELETE']) def api_posts_detail(request, pk): post = get_object_or_404(Post, id=pk) # напишем обработчик для метода GET if request.method == 'GET': serializer = PostSerializer(post) return Response(serializer.data) # получаем пользователя из запроса user = request.user # если пользователь, обратившийся к API, не является автором поста, # то к методам, идущим после GET, мы его не пропускаем # и возвращаем ответ со статусом 403 if user != post.author: return Response(status=status.HTTP_403_FORBIDDEN) if request.method == 'PUT' or request.method == 'PATCH': serializer = PostSerializer(post, data=request.data, partial=True) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': post.delete() return Response(status=status.HTTP_204_NO_CONTENT)
Код urls.py:
from django.urls import path, include from .views import api_posts, api_posts_detail from rest_framework.authtoken import views urlpatterns = [ path('api/v1/posts/', api_posts), path('api/v1/posts/<int:pk>/', api_posts_detail), path('api/v1/api-token-auth/', views.obtain_auth_token), ]