Django Rest Framework中下拉选择框接口PUT方法失效问题排查
api/root) Hey there, let's break down why your PUT request isn't working for the api/root dropdown selection endpoint and how to fix it.
The Root Cause
Looking at your ProductEnquirySerializer, you've defined the productname field like this:
productname = serializers.CharField(source='productname.pro_name')
While this works great for serializing (outputting the pro_name of the linked Product), it doesn't handle deserialization (processing incoming data for PUT updates).
This field is effectively read-only in its current setup—DRF doesn't know how to take a string pro_name and map it back to the actual Product instance that the ProductEnquiry should be linked to. So when you send a PUT request, the productname value gets ignored, and the update fails to modify that field.
Solution 1: Use Primary Key for Updates (Recommended)
If your frontend can send the id of the selected Product instead of the pro_name, this is the simplest fix. Use PrimaryKeyRelatedField which handles both serialization and deserialization for foreign keys:
class ProductEnquirySerializer(serializers.HyperlinkedModelSerializer): # Add a read-only field to return the pro_name in responses product_name = serializers.CharField(source='productname.pro_name', read_only=True) # Use this field for creating/updating the foreign key relationship productname = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all()) class Meta: model = ProductEnquiry fields = ('id', 'productname', 'product_name', 'qty')
- When you send a PUT request, you can pass the
productnameas the Product'sid(e.g.,{"productname": 1, "qty": "5"}). - The
product_namefield will still return the human-readablepro_namein API responses for your dropdown.
Solution 2: Handle pro_name String in Updates
If your frontend must send the pro_name string instead of the ID, you'll need to override the serializer's update method to manually map the string to a Product instance:
class ProductEnquirySerializer(serializers.HyperlinkedModelSerializer): productname = serializers.CharField(source='productname.pro_name') class Meta: model = ProductEnquiry fields = ('id', 'productname', 'qty') def update(self, instance, validated_data): # Extract the pro_name from the validated data product_data = validated_data.pop('productname') pro_name = product_data['pro_name'] # Find the corresponding Product instance # Note: Add error handling here if the pro_name doesn't exist! try: product = Product.objects.get(pro_name=pro_name) except Product.DoesNotExist: raise serializers.ValidationError(f"Product with name '{pro_name}' does not exist.") except Product.MultipleObjectsReturned: raise serializers.ValidationError(f"Multiple products found with name '{pro_name}'. Use ID instead.") # Update the instance fields instance.productname = product instance.qty = validated_data.get('qty', instance.qty) instance.save() return instance
⚠️ Important: This assumes pro_name is unique in your Product model. If not, add a unique constraint to pro_name in models.py or adjust the query to handle duplicates.
Final Notes
Test your PUT request after implementing either solution. For example, with Solution 1, a valid PUT body might look like:
{ "productname": 2, "qty": "10" }
And the response will include the product_name field with the corresponding Product's name.
内容的提问来源于stack exchange,提问作者keerthana devi

