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