Serializing Dict Field inside List : ValueError: Cannot assign "OrderedDict

I am expanding JSON data from my last question and trying to save it to the database. Period model contains startDate and endDate because the JSON object could have all 3, or maybe one of them so I want to make them options.

I am following steps given in the documentation for Writable nested representation but I am unable to get the same results

Commented out code are the attempts I made to get the data to save.

When I am trying to save the data, I get

ValueError: Cannot assign "OrderedDict([('instant', '2020-09-26')])": "Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.period" must be a "Period" instance.

Models:

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)


class Period(models.Model):
    period = models.AutoField(primary_key=True)
    instant = models.CharField(blank=False, max_length=100, null=True)
    startDate = models.CharField(blank=False, max_length=255, null=True)
    endDate = models.CharField(blank=False, max_length=255, null=True)
    cashcashequivalentsrestrictedcashandrestrictedcashequivalents_id = models.OneToOneField(
        Cashcashequivalentsrestrictedcashandrestrictedcashequivalents, on_delete=models.CASCADE)

Serializer:

class PeriodSerializer(serializers.ModelSerializer):
    # instant = serializers.DictField(
    #     child=serializers.CharField(required=False, max_length=255))
    # startDate = serializers.DictField(
    #     child=serializers.CharField(required=False, max_length=255))
    # endDate = serializers.DictField(
    #     child=serializers.CharField(required=False, max_length=255))
    instant = serializers.CharField(required=False, max_length=255)
    startDate = serializers.CharField(required=False, max_length=255)
    endDate = serializers.CharField(required=False, max_length=255)
    cashcashequivalentsrestrictedcashandrestrictedcashequivalents_id = serializers.IntegerField(
        required=False)

    class Meta:
        model = Period
        fields = "__all__"


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')
        if period_data:
            period = Period.objects.create(**period_data)
            itemOne = Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.objects.create(
                cashcashequivalentsrestrictedcashandrestrictedcashequivalents_id=period, **period_data)
            return itemOne

    # def create(self, validated_data):
    #     print("validated_data", validated_data)
    #     instant = ''
    #     startDate = ''
    #     endDate = ''
    #     if (validated_data.get('period').get("instant")):
    #         instant = validated_data.get('period').get("instant")
    #     else:
    #         instant = None
    #     if (validated_data.get('period').get("startDate")):
    #         startDate = validated_data.get('period').get("startDate")
    #     else:
    #         startDate = None
    #     if (validated_data.get('period').get("endDate")):
    #         endDate = validated_data.get('period').get("endDate")
    #     else:
    #         endDate = None

    #     period = Period.objects.create(
    #         **{"instant": instant, "startDate": startDate, "endDate": endDate})
    #     itemOne = Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.objects.create(
    #         cashcashequivalentsrestrictedcashandrestrictedcashequivalents_id=period, **validated_data)
    #     return period


class CashFlowSerializer(serializers.ModelSerializer):
    CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents = CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer(
        many=True)

    class Meta:
        model = Basetable
        fields = "__all__"
        
    def create(self, validated_data):
        itemOneData = validated_data.pop(
            'CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents')
        cashflow = Basetable.objects.create(**validated_data)
        for data in itemOneData:
            Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.objects.create(
                basetable_id=cashflow, **data)
        return cashflow

View:

def companyApiCall(request):
    if request.method == 'GET':
        jsonToUse = {
            "CompanyId": "320193",
            "CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents": [
                {
                    "decimals": "-6",
                    "unitRef": "usd",
                    "period": {
                        "instant": "2020-09-26"
                    },
                    "value": "39789000000"
                },
                {
                    "decimals": "-6",
                    "unitRef": "usd",
                    "period": {
                        "instant": "2019-09-28"
                    },
                    "value": "50224000000"
                },
                {
                    "decimals": "-6",
                    "unitRef": "usd",
                    "period": {
                        "instant": "2018-09-29"
                    },
                    "value": "25913000000"
                }
            ]
        }
        check = CashFlowSerializer(data=jsonToUse)
        if (check.is_valid(raise_exception=True)):
            print("ready to send to db")
            check.save()
        return JsonResponse(jsonToUse, safe=False)

Thank you for the time and help

In your CashFlowSerializer, try this (added in-line comments to explain the changes):

class CashFlowSerializer(serializers.ModelSerializer):
    CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents = CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsSerializer(many=True)

    class Meta:
        model = Basetable
        fields = "__all__"
        
    def create(self, validated_data):
        itemOneData = validated_data.pop('CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents')

        cashflow = Basetable.objects.create(**validated_data)

        for data in itemOneData:
            # Pop the period data because the long-named model 
            # is not happy with it and cannot process it
            period_data = data.pop("period") 

            my_long_named_obj = Cashcashequivalentsrestrictedcashandrestrictedcashequivalents.objects.create(basetable_id=cashflow, **data)

            # Handle the period data and assign the newly created long-named model object
            my_period_object = Period.objects.create(
                cashcashequivalentsrestrictedcashandrestrictedcashequivalents_id=my_long_named_obj,
                **period_data,
            )

        return cashflow
Back to Top