以下是我的问题的一些简化代码片段:
Django模型:
class Champion(models.Model):
id = models.PositiveIntegerField(primary_key=True)
name = models.CharField(max_length=30)
# spells ([List] through ForeignKey in ChampionSpells)
# passive (through ForeignKey in ChampionPassive)
def __str__(self):
return self.name
class ChampionPassive(models.Model):
champion = models.ForeignKey(Champion, related_name='passive', related_query_name='passive')
description = models.TextField()
name = models.CharField(max_length=30)
class ChampionSpell(models.Model):
champion = models.ForeignKey(Champion, related_name='spells', related_query_name='spell')
cooldownBurn = models.CharField(max_length=40)
costBurn = models.CharField(max_length=40)
costType = models.CharField(max_length=10)
# image (through ForeignKey in ChampionImageInfo)
class SpellImageInfo(models.Model):
spell = models.ForeignKey(ChampionSpell, related_name='image', related_query_name='image')
full = models.CharField(max_length=200)
group = models.CharField(max_length=200)
串行器:
class ChampionPassiveSerializer(serializers.ModelSerializer):
class Meta:
model = ChampionPassive
exclude = ('champion',)
class SpellImageInfoSerializer(serializers.ModelSerializer):
class Meta:
model = SpellImageInfo
exclude = ('spell',)
class ChampionSpellSerializer(serializers.ModelSerializer):
# after adding this field, i get a TypeError
image = SpellImageInfoSerializer()
class Meta:
model = ChampionSpell
exclude = ('champion',)
class ChampionSerializer(serializers.ModelSerializer):
passive = ChampionPassiveSerializer()
spells = ChampionSpellSerializer(many=True)
class Meta:
model = Champion
def create(self, validated_data):
spells_data = validated_data.pop('spells')
passive_data = validated_data.pop('passive')
champion = Champion.objects.create(**validated_data)
for spell_data in spells_data:
spell = ChampionSpell.objects.create(champion=champion, **spell_data)
spell_image_data = spell_data.pop('image')
SpellImageInfo.objects.create(spell=spell, **spell_image_data)
ChampionPassive.objects.create(champion=champion, **passive_data)
return champion
要反序列化的JSON数据:
{
"id": 1,
"name": "Annie",
"spells": [{
"name": "Disintegrate",
"description": "Annie hurls a Mana infused fireball, dealing damage and refunding the Mana cost if it destroys the target.",
"image": {
"full": "Disintegrate.png",
"group": "spell"
},
"cooldownBurn": "4",
"costType": "Mana",
"costBurn": "60\/65\/70\/75\/80"
}, {
"name": "Incinerate",
"description": "Annie casts a blazing cone of fire, dealing damage to all enemies in the area.",
"image": {
"full": "Incinerate.png",
"group": "spell"
},
"cooldownBurn": "8",
"costType": "Mana",
"costBurn": "70\/80\/90\/100\/110"
}],
"passive": {
"name": "Pyromania",
"description": "After casting 4 spells, Annie's next offensive spell will stun the target for a short duration."
}
}
请注意,我对JSON的结构没有任何影响,因为我从流行的在线游戏“英雄联盟”的游戏api中得到了这个结构。我为这个例子简化了很多,还有更多的字段和更多的深度。
我开始只对最高级别的Champion字段进行反序列化,效果很好。比起我添加了ChampionSpells和ChampionPassive而没有更深层次的东西,这些厚实的内容也很好。
当我添加第二个深度级别并将SpellImageInfo包含在ChampionSpell反序列化中时,我收到以下错误:
----------------------------------------------------------------------
File "/home/ubuntu/workspace/lolstatistics/stats/serializers.py", line 111, in create
spell = ChampionSpell.objects.create(champion=champion, **spell_data)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 122, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 399, in create
obj = self.model(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 443, in __init__
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'image' is an invalid keyword argument for this function
----------------------------------------------------------------------
is_valid()
方法的执行返回True
但是当我调用ChampionSerializer的save()
方法时,我收到此错误。我无法弄清楚原因,因为image
绝对是ChampionSpell
模型中通过SpellImageInfo
内的ForeignKey的字段。此外,对于一个深度较少的水平(离开SpellImageInfo),它工作正常。
有人对此有解决方案或解释吗?
答案 0 :(得分:0)
我不确定这正是你所追求的,但也许它至少是你正确方向的开始:
import json
j = """{
"id": 1,
"name": "Annie",
"spells": [{
"name": "Disintegrate",
"description": "Annie hurls a Mana infused fireball, dealing damage and refunding the Mana cost if it destroys the target.",
"image": {
"full": "Disintegrate.png",
"group": "spell"
},
"cooldownBurn": "4",
"costType": "Mana",
"costBurn": "60\/65\/70\/75\/80"
}, {
"name": "Incinerate",
"description": "Annie casts a blazing cone of fire, dealing damage to all enemies in the area.",
"image": {
"full": "Incinerate.png",
"group": "spell"
},
"cooldownBurn": "8",
"costType": "Mana",
"costBurn": "70\/80\/90\/100\/110"
}],
"passive": {
"name": "Pyromania",
"description": "After casting 4 spells, Annie's next offensive spell will stun the target for a short duration."
}
}"""
class DeserializeJSON(object):
def __init__(self, j):
self.__dict__ = json.loads(j)
d = DeserializeJSON(j)
print(d.id)
print(d.name)
print()
print(d.spells[0]["name"])
print()
print(d.spells[0]["image"]["full"])
print()
print(d.passive["name"])
print()
for k, v in enumerate(d.spells):
print(k)
print(v["name"])
print(v["description"])
print()
输出:
1
Annie
Disintegrate
Disintegrate.png
Pyromania
0
Disintegrate
Annie hurls a Mana infused fireball, dealing damage and refunding the Mana cost if it destroys the target.
1
Incinerate
Annie casts a blazing cone of fire, dealing damage to all enemies in the area.