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

Django DRF嵌套序列化报错:无法将OrderedDict赋值为Period实例

问题解决:嵌套序列化保存时的实例赋值错误

报错根源

报错ValueError: Cannot assign "OrderedDict([('instant', '2020-09-26')])": "Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.period" must be a "Period" instance的核心原因有三点:

  1. 模型关联关系倒置:Period模型的OneToOneField指向了Cashcashequivalentsrestrictedcashandrestrictedcashequivalents,但实际业务逻辑应该是后者包含一个指向Period的一对一关联(每个现金条目对应一个时间周期)。
  2. 序列化器create方法逻辑错误:CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer的create方法中,创建现金条目时错误传入了period_data,且混淆了模型间的关联字段名。
  3. 顶层序列化器绕开嵌套处理:CashFlowSerializer的create方法直接调用模型create处理嵌套数据,未触发嵌套序列化器对period字段的解析逻辑。

分步修复

1. 修正模型关联关系

调整模型间的一对一关联方向,让现金条目拥有指向Period的字段:

class Basetable(models.Model):
    basetable = models.AutoField(primary_key=True)
    CompanyId = models.IntegerField()


class Cashcashequivalentsrestrictedcashandrestrictedcashequivalents(models.Model):
    cashtable = models.AutoField(primary_key=True)
    unitRef = models.CharField(max_length=100)
    value = models.CharField(max_length=100)
    decimals = models.CharField(max_length=100)
    basetable_id = models.ForeignKey(Basetable, on_delete=models.CASCADE)
    # 添加指向Period的一对一字段
    period = models.OneToOneField(Period, on_delete=models.CASCADE, related_name='cash_entry')


class Period(models.Model):
    period = models.AutoField(primary_key=True)
    # 改为blank=True,支持字段可选
    instant = models.CharField(blank=True, max_length=100, null=True)
    startDate = models.CharField(blank=True, max_length=255, null=True)
    endDate = models.CharField(blank=True, max_length=255, null=True)

2. 修正嵌套序列化器的create方法

调整CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer的逻辑,正确创建并关联Period实例:

class PeriodSerializer(serializers.ModelSerializer):
    class Meta:
        model = Period
        fields = ['instant', 'startDate', 'endDate']


class CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer(serializers.ModelSerializer):
    period = PeriodSerializer(many=False)

    class Meta:
        model = Cashcashequivalentsrestrictedcashandrestrictedcashequivalents
        fields = ['decimals', 'unitRef', 'value', 'period']

    def create(self, validated_data):
        period_data = validated_data.pop('period')
        # 创建Period实例
        period = Period.objects.create(**period_data)
        # 创建现金条目并关联period
        cash_entry = Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.objects.create(period=period, **validated_data)
        return cash_entry

3. 修正顶层序列化器的create方法

通过嵌套序列化器处理现金条目数据,确保触发嵌套字段的解析逻辑:

class CashFlowSerializer(serializers.ModelSerializer):
    # 指定source匹配模型的反向关联名称
    CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents = CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer(
        many=True, source='cashcashequivalentsrestrictedcashandrestrictedcashequivalents_set')

    class Meta:
        model = Basetable
        fields = ['CompanyId', 'CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents']
        
    def create(self, validated_data):
        cash_entries_data = validated_data.pop('cashcashequivalentsrestrictedcashandrestrictedcashequivalents_set')
        basetable = Basetable.objects.create(**validated_data)
        for entry_data in cash_entries_data:
            # 使用嵌套序列化器创建条目,自动处理period字段
            serializer = CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer(data=entry_data)
            serializer.is_valid(raise_exception=True)
            serializer.save(basetable_id=basetable)
        return basetable

4. 视图代码无需修改

原视图的JSON数据格式符合要求,修复上述代码后,check.save()会正常触发嵌套序列化的保存逻辑。

验证结果

运行视图的GET请求后,数据库会正确生成:

  • 1条Basetable记录(对应CompanyId=320193)
  • 3条Cashcashequivalentsrestrictedcashandrestrictedcashequivalents记录,分别关联对应的Period实例
  • 3条Period记录,各自保存对应的instant值

内容的提问来源于stack exchange,提问作者Maddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:27:41