我的模特:
class Item(models.Model):
wiki_url = models.URLField(_('wiki url'))
img_url = models.URLField(_('img url'))
name = models.CharField(_('name'), max_length=255, unique=True)
item_id = models.PositiveIntegerField(_('item id'), unique=True, db_index=True) # refers to ingame_id
child_items = models.ManyToManyField(
'Item',
through='Recipe',
)
def __str__(self):
return f'{self.name}'
class Recipe(models.Model):
parent_item = models.ForeignKey(Item, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='child_item')
quantity = models.PositiveSmallIntegerField(_('quantity'))
class Meta:
unique_together = ['parent_item', 'item']
def __str__(self):
return f'{self.quantity}x {self.item}'
我想要得到什么:
{
"item_id": 5265,
"name": "A",
"wiki_url": "some_url",
"img_url": "some_url",
"children": [
{
"item_name": "B",
"item_id": 5194,
"wiki_url": "some_url",
"img_url": "some_url",
"quantity": 248,
"children": []
},
{
"item_name": "C",
"item_id": 3950,
"wiki_url": "some_url",
"img_url": "some_url",
"quantity": 1000,
"children": [
{
"item_name": "D",
"item_id": 5194,
"wiki_url": "some_url",
"img_url": "some_url",
"quantity": 248,
"children": []
}
]
}
]
},
基本上,我想获得item
的嵌套(最多4个)及其通过模型quantity
中的Recipe
值。
此刻,我的序列化器如下:
class RecipeSerializer(ModelSerializer):
item_name = ReadOnlyField(source='item.name')
item_id = ReadOnlyField(source='item.item_id')
wiki_url = ReadOnlyField(source='item.wiki_url')
img_url = ReadOnlyField(source='item.img_url')
class Meta:
model = Recipe
fields = ('item_name', 'item_id', 'wiki_url', 'img_url', 'quantity')
class ItemSerializer(ModelSerializer):
children = RecipeSerializer(source='recipe_set', many=True)
class Meta:
model = Item
fields = ('item_id', 'name', 'wiki_url', 'img_url', 'children')
目前,只有一层嵌套-即children
没有后续的children
。我认为应该发生的是,ItemSerializer
在RecipeSerializer
内部用source='item'
简单地调用。但是,这是不可能的,因为RecipeSerializer
内部已经调用了ItemSerializer
,这意味着必须使用字符串名称(例如类似serializers.GetSerializer('apps.myapp.serializers.ItemSerializer')(source='item')
的字符串)来调用它
解决这个问题的正确方法是什么?
编辑: 这些值或多或少是固定的,并且永远不会超过嵌套深度3/4。
编辑: 我使用它来工作:
class RecursiveSerializer(Serializer):
def to_representation(self, instance):
data = dict(ItemSerializer(instance=instance.item, context=self.context).data)
data.update({'quantity': instance.quantity})
return data
class ItemSerializer(ModelSerializer):
children = RecursiveSerializer(many=True, read_only=True, source='recipe_set')
class Meta:
model = Item
fields = ('item_id', 'name', 'wiki_url', 'img_url', 'children')
但是,现在的问题是该方法没有利用prefetched
项,即即使预取了数据也有n + 1个查询。预取对于使查询高效至关重要,因此解决方案必须利用预取的值。