En una aplicación de Django Rest Framework, hay un TextViewSet. La estructura del objeto Texto es la siguiente:
{ text: text_value, author: author_id }Al crear una nueva instancia de Text, quiero verificar si el author_id proporcionado es igual al ID del usuario que ha iniciado sesión actualmente.
He leído esta pregunta: Cuándo usar create() de Serializer y perform_create() de ModelViewset , pero aún no puedo decidir si anular los métodos create() de Serializer, create() o perform_create() de ModelViewset. ¿Cuál es el método correcto para anular?
UPD:
modelos.py :
class Text(models.Model): text = models.TextField() author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)serializadores.py:
class TextSerializer(serializers.ModelSerializer): class Meta: model = Text fields = ['author', 'text'] La pregunta es en cuál de estos métodos se debe realizar esta verificación if self.request.user.id != self.request.data['author']: ?
Puede anular create() el método de su TextViewSet
vistas.py
from rest_framework.response import Response class TextViewSet(ModelViewSet): def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) if request.user.id == request.data['author']: self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) else: return Response("Unauthorized", status=status.HTTP_401_UNAUTHORIZEDLa verdadera pregunta es ¿por qué no simplemente configurar el autor para el usuario que inició sesión y no permitir que el cliente envíe ninguna identificación?
La forma normal de hacer esto es por:
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, ie the logged in user, for fetching/updating data''' return self.queryset.filter(author=self.request.user)Pero si realmente desea enviar una identificación de autor, también puede usar un Permiso personalizado para que sea reutilizable.
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) )Usado como:
class ExampleViewSet(ModelViewSet): permission_classes = [UserIsAuthor] # optional if the default "author" isnt what you want. permission_author_field = "some_field_in_request_data"