You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  1. User ID Handling: I added user = self.context['request'].user to populate the user_id field. If you're not using authenticated users, adjust this to get the user ID from your request context or another source.
  2. API Semantics: Since your POST request is updating/creating RfiParticipation entries (not creating new Vendors), you might want to consider using a UpdateAPIView or a custom view instead of ListCreateAPIView for better RESTful semantics. However, the above fix will work with your existing view setup.
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:14:05