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)