Search code examples
pythondjangoapidjango-rest-frameworkdjango-rest-viewsets

Get Authenticated user on many=True serializer Viewset


I'm writing a rest api using Django Rest Framework, I have an endpoint to create objects on POST method and this method is overridden in order to allow bulk adding. However, the object is an "intermediate table" between Pacient and Symptoms and in order to create it I need to provide the pacient object or id and the same for the symptom. I get the Symptom id in the request, so that's not an issue, however the pacient is the authenticated user (who's making the request). Now, how do I edit the create method in the serializer in order to do that?

Here's my view:

class PacienteSintomaViewSet(viewsets.ModelViewSet):
    serializer_class = SintomaPacienteSerializer
    queryset = SintomaPaciente.objects.all()
    permission_classes = (IsAuthenticated, )
    http_method_names = ['post', 'get']

    def create(self, request, *args, **kwargs):
        many = True if isinstance(request.data, list) else False
        serializer = SintomaPacienteSerializer(data=request.data, many=many)
        if serializer.is_valid():
            sintomas_paciente_lista = [SintomaPaciente(**data) for data in serializer.validated_data]
            print(serializer.validated_data)
            SintomaPaciente.objects.bulk_create(sintomas_paciente_lista)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

And this is my serializer:

class SintomaPacienteSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        sintoma_paciente = SintomaPaciente.objects.create(
            sintoma_id=self.validated_data['sintoma_id'],
            paciente_id=THIS NEEDS TO BE FILLED,
            data=self.validated_data['data'],
            intensidade=self.validated_data['intensidade'],
        )
        return sintoma_paciente

    class Meta:
        model = SintomaPaciente
        fields = ('id', 'sintoma_id', 'paciente_id', 'intensidade', 'data',
                  'primeiro_dia', 'ativo')


Solution

  • There is two way. First one, you can pass your user to serializer inside context, and use it in serializer:

    in your view:

    def create(self, request, *args, **kwargs):
        many = True if isinstance(request.data, list) else False
        serializer = SintomaPacienteSerializer(data=request.data, many=many,context={'user':request.user})
    

    in your serializer you can access this user with self.context['user']

    Second way, you don't need to pass user to serializer again. Also If you already override the create method in your View, you don't need to override create method in serializer. I think it is wrong logically. Anyway, you can use your user when create object in view:

    def create(self, request, *args, **kwargs):
        many = True if isinstance(request.data, list) else False
        serializer = SintomaPacienteSerializer(data=request.data, many=many)
        if serializer.is_valid():
            sintomas_paciente_lista = [SintomaPaciente(**data,paciente_id=request.user.id) for data in serializer.validated_data]
            print(serializer.validated_data)
            ....