Django Rest Frame Work: passing User in djago rest frame work

Solution 1:

Your serializer has no idea about the currently logged-in user.You to pass it as context from request. user or request.

I personally prefer CurrentUserDefault to be used in the serializer. To make it work we need to pass the request as context because CurrentUserDefault picks user from context request. We need to update our views and serializer code as follows

Views file: Add request as context context

class ReportCreateView(APIView):


def post(self,request, *args, **kwargs):
    received_data=ReportSerializer(data=request.data, context = {"request": request})
    if received_data.is_valid():
        received_data.save()
        return Response(received_data.data, status=status.HTTP_201_CREATED)
    return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)

serializer.py: Update your serializer to auto-populate created_by_user

class ReportSerializer(serializers.ModelSerializer):
    created_by_user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    
    class Meta:
        model=Report
        fields='__all__'

It will solve your user field required issue.

"created_by_user": ["This field is required."]

Now coming to your next part of the issue that is related to incorrect passwords.

By default, APIView picks the default authentication class from settings. Inside projects settings.py, we mostly write these lines while using DRF and they serve as default authentication for APIView:

From settings.py

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    # Authentication settings
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.SessionAuthentication",
    ],
   ...
}

Inside APIView you can have a look at default permission_classes, and authentication_classes

From inside APIView:

    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES

that is when you type an invalid password:

"detail": "Invalid username/password."

Provide the correct username and password to your APIView from postman so that it gets the requested logged-in user for auto-populates at DB level.

Cheers!

Solution 2:

you don't perform any process on your user data and just need to save the request user, due to that I think you don't need a serializer field for it and it's better to get your current user in view. also if you need more fields to serialize, you can make created_by_user read_only true and set its value on your view.

for example, if you have report name and report desc field in your model:

class Report(models.Model):
    created_by_user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=256)
    desc = models.TextField()

perform your serializer like this :

class ReportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Report
        fields = '__all__'
        extra_kwargs = {
            'created_by_user': {'read_only': True},
        }

then set created_by_user value in your view:

class ReportCreateView(APIView):
    def post(self, request, *args, **kwargs):
        request.data['created_by_user'] = request.user # just need add this line 
        received_data = ReportSerializer(data=request.data)
        if received_data.is_valid():
            received_data.save()
            return Response(received_data.data, status=status.HTTP_201_CREATED)
        return Response(received_data.errors, status.HTTP_400_BAD_REQUEST)