Создавать экземпляр модели, только если поле id пользователя равно id вошедшего пользователя
В приложении django rest framework есть TextViewSet. Структура объекта Text выглядит следующим образом:
{
text: text_value,
author: author_id
}
При создании нового экземпляра Text я хочу проверить, равен ли указанный author_id идентификатору текущего зарегистрированного пользователя.
Я прочитал такой вопрос: Когда использовать Serializer's create() и ModelViewset's perform_create(), но все еще не могу решить, какой метод переопределить: Serializer's create(), ModelViewset's create() или perform_create(). Какой метод следует переопределить?
UPD:
models.py:
class Text(models.Model):
text = models.TextField()
author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
serializers.py:
class TextSerializer(serializers.ModelSerializer):
class Meta:
model = Text
fields = ['author', 'text']
Вопрос в том, в каком из этих методов следует выполнить эту проверку if self.request.user.id != self.request.data['author']:
?
Вы можете переопределить create()
метод вашего TextViewSet
views.py
from rest_framework.response import Response
class TextViewSet(ModelViewSet):
...
def create(self, request, *args, **kwargs):
if self.request.user.id != self.request.data['author']:
serializer = TextSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response({error: serializer.errors})
else:
return Response({error: "Invalid User"})
Настоящий вопрос заключается в том, почему бы просто не установить author на пользователя, вошедшего в систему, и не позволять клиенту посылать какой-либо ID вообще?
Обычный способ сделать это заключается в следующем:
class MyViewSet(ModelViewSet):
...
def perform_create(self, serializer):
'''The logged in user is always the author'''
return serializer.save(author=self.request.user)
def get_queryset(self):
'''Limit the queryset to the author, i.e the logged in user, for fetching/updating data'''
return self.queryset.filter(author=self.request.user)
Но если вы действительно хотите передавать идентификатор автора, вы также можете использовать пользовательское разрешение для этого, чтобы его можно было использовать повторно.
from rest_framework.permissions import BasePermission
class UserIsAuthor(BasePermission):
default_author_field = "author"
def has_permission(self, request, view):
author_field = getattr(
view,
"permission_author_field",
self.default_author_field
)
return request.user.is_authenticated and (
request.user.pk == request.data.get(author_field)
)
используется как:
class ExampleViewSet(ModelViewSet):
permission_classes = [UserIsAuthor]
# optional if the default "author" isnt what you want.
permission_author_field = "some_field_in_request_data"