Django REST Framework: “Este campo es obligatorio.” Con required = False y unique_together

Quiero guardar un modelo simple con Django REST Framework. El único requisito es que UserVote.created_by se establezca automáticamente dentro del método perform_create() . Esto falla con esta excepción:

 { "created_by": [ "This field is required." ] } 

Supongo que es debido al índice unique_together.

modelos.py:

 class UserVote(models.Model): created_by = models.ForeignKey(User, related_name='uservotes') rating = models.ForeignKey(Rating) class Meta: unique_together = ('created_by', 'rating') 

serializers.py

 class UserVoteSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) created_by = UserSerializer(read_only=True) class Meta: model = UserVote fields = ('id', 'rating', 'created_by') 

vistas.py

 class UserVoteViewSet(viewsets.ModelViewSet): queryset = UserVote.objects.all() serializer_class = UserVoteSerializer permission_classes = (IsCreatedByOrReadOnly, ) def perform_create(self, serializer): serializer.save(created_by=self.request.user) 

¿Cómo puedo guardar mi modelo en DRF sin que el usuario proporcione created_by y, en su lugar, establezca este campo automáticamente en código?

¡Gracias por adelantado!

Tuve un problema similar y lo resolví creando y pasando explícitamente una nueva instancia al serializador. En el UserVoteViewSet debes sustituir perform_create con create :

  def create(self, request, *args, **kwargs): uv = UserVote(created_by=self.request.user) serializer = self.serializer_class(uv, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

La otra forma extraña que puedes hacer es usar señales como esta

 @receiver(pre_save, sender=UserVote) def intercept_UserVote(sender, instance, *args, **kwargs): import inspect for frame_record in inspect.stack(): if frame_record[3]=='get_response': request = frame_record[0].f_locals['request'] break else: request = None instance.pre_save(request) 

Entonces básicamente puedes definir pre_save en tu modelo.

 def pre_save(self, request): # do some other stuff # Although it shouldn't happen but handle the case if request is None self.created_by = request.user 

La ventaja de este sistema es que puede usar el mismo bit de código para cada modelo. Si necesita cambiar algo, simplemente cambie en pre_save() . Puedes agregar más cosas también

Pude resolver esto con una sola línea en views.py

 def create(self, request, *args, **kwargs): request.data.update({'created_by': request.user.id}) return super(UserVoteViewSet, self).create(request, *args, **kwargs) 

Como esta vista espera que el usuario esté autenticado, no olvide extender permission_classes para rest_framework.permissions.IsAuthenticated