DRF中如何通过JWT设置预约表user_id字段并写入数据库
Ah, I see the issue here! You're using a SerializerMethodField to handle user_id, but that field is read-only by default — it only generates values for the response output, not for saving data to the database. That's why your user_id is always stuck at the default 0.
Let's fix this with a couple of straightforward changes. Here are two reliable approaches:
Approach 1: Pass user_id directly in perform_create (simplest)
This is the most straightforward way. We'll mark user_id as read-only in the serializer, then inject it when saving the instance.
Update your serializer.py:
class requestReservationSerailizer(ModelSerializer): class Meta: model = reservations fields = ['pet_id', 'user_id', 'location', 'arrival', 'depature', 'comments'] read_only_fields = ['user_id'] # Prevent frontend from overriding this value
Update your view.py:
class requestReservation(CreateAPIView): serializer_class = requestReservationSerailizer permission_classes = [IsAuthenticated] def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response( {"message":"Success","status_message":"Reservation Created Successfully"}, status=status.HTTP_200_OK, headers=headers ) def perform_create(self, serializer): # Inject the authenticated user's ID directly when saving serializer.save(user_id=self.request.user.id)
Approach 2: Use serializer context and override create method
If you prefer handling the logic within the serializer, you can pull the user_id from the context and add it to the validated data before creating the instance.
Update your serializer.py:
class requestReservationSerailizer(ModelSerializer): class Meta: model = reservations fields = ['pet_id', 'user_id', 'location', 'arrival', 'depature', 'comments'] read_only_fields = ['user_id'] def create(self, validated_data): # Grab user_id from the context passed by the view user_id = self.context.get('user_id') # Merge it with the validated data and create the reservation instance return super().create({**validated_data, 'user_id': user_id})
Update your view.py:
class requestReservation(CreateAPIView): serializer_class = requestReservationSerailizer permission_classes = [IsAuthenticated] def get_serializer_context(self): # Add the authenticated user's ID to the serializer context context = super().get_serializer_context() context['user_id'] = self.request.user.id return context def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response( {"message":"Success","status_message":"Reservation Created Successfully"}, status=status.HTTP_200_OK, headers=headers )
Why your original code didn't work
SerializerMethodField is designed to generate dynamic values for response serialization (when sending data back to the client). It doesn't participate in deserialization (processing incoming data to save to the database). So even though you set obj.user_id in your set_user_id method, that change never gets passed to the database save operation.
Either of the above approaches will ensure the user_id from your JWT-authenticated user gets saved correctly to the reservations table.
内容的提问来源于stack exchange,提问作者Vallabh

