Добавьте механизм аутентификации при помощи обычного токена в проект 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),
]