DRF中ListCreateAPIView与嵌套序列化器的使用问题排查
Let's break down your two issues and fix them with targeted adjustments to your code:
问题1:POST单个字典报错,必须传数组
原因
Your to_vendor field uses many=True in the nested serializer, so DRF expects a list of objects by default. When you send a single dictionary without wrapping it in an array, the serializer validation fails because it's not the expected type.
解决方案
Modify the create method in VendorModulesListManagementSerializer to automatically convert a single dictionary into a list. This makes your API compatible with both single and multiple module entries in the POST request.
问题2:AttributeError after create (no 'to_vendor' on RfiParticipation)
原因
Your create method returns a RfiParticipation instance, but your serializer is tied to the Vendors model. When DRF tries to serialize the response, it looks for the to_vendor field (a related name for Vendors) on the returned RfiParticipation object, which doesn't exist—hence the error. The correct return value should be a Vendors instance, matching your serializer's model.
解决方案
Update the create method to return the corresponding Vendors object after processing all module entries. Also, we'll add proper handling for the user_id field (since it's required in your RfiParticipation model but wasn't being set in your original code).
Updated Serializer Code (serializer.py)
class VendorModulesListManagementSerializer(serializers.ModelSerializer): to_vendor = RfiParticipationSerializer(many=True) class Meta: model = Vendors fields = ('vendorid', 'vendor_name', 'to_vendor',) read_only_fields = ('vendorid', 'vendor_name', ) def create(self, validated_data): # Extract module data and handle single dict case vendor_modules_data = validated_data.pop('to_vendor') if isinstance(vendor_modules_data, dict): vendor_modules_data = [vendor_modules_data] # Get the current user from the request (adjust if your auth is different) user = self.context['request'].user target_vendor = None for module_data in vendor_modules_data: # Fetch the vendor instance once per entry (or reuse if all are same vendor) vendor = Vendors.objects.get(pk=module_data['vendor']) target_vendor = vendor # Store to return later # Update or create the RfiParticipation entry RfiParticipation.objects.update_or_create( rfi=module_data.get('rfi', None), vendor=vendor, m=module_data.get('m', None), defaults={ 'active': module_data.get('active', False), 'user_id': user.id # Set user_id from the authenticated user } ) # Return the Vendors instance to match the serializer's model return target_vendor class RfiParticipationSerializer(serializers.ModelSerializer): class Meta: model = RfiParticipation fields = ('pk', 'active', 'm', 'rfi', 'vendor', 'timestamp') read_only_fields = ('timestamp', )
Additional Notes
- User ID Handling: I added
user = self.context['request'].userto populate theuser_idfield. If you're not using authenticated users, adjust this to get the user ID from your request context or another source. - API Semantics: Since your POST request is updating/creating
RfiParticipationentries (not creating newVendors), you might want to consider using aUpdateAPIViewor a custom view instead ofListCreateAPIViewfor better RESTful semantics. However, the above fix will work with your existing view setup. - Validation: You might want to add extra validation to ensure all module entries in the POST request belong to the same vendor, if that's a requirement for your use case.
内容的提问来源于stack exchange,提问作者Jekson

