问题描述
不想创建太大的问题,但是为了更加清晰起见,我实际上在我的 Menu
类中有另一个对象,例如:
类菜单(models.Model):
title = models.CharField(max_length = 255)
image = models.URLField (blank = True,null = True)
价格= models.FloatField(blank = True,null = True,max_length = 255)
成分= StreamField([
('zutaten',IngredientChooserBlock ('kitchen.Ingredient'))],
null = True,verbose_name ='',blank = True)
步骤= StreamField([
('Schritt',TextBlock())
],null = True,verbose_name ='Vorbereitungsschritte',空白= True)
,我也想代表他们。但是仅当我尝试输出 StreamField
类WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self,value,context = None):
if value:
return {
'title':value.title,
'图片':value.image,
'price':value.price,
'ingredients':value.ingredient,
'steps':value.steps
}
感谢您的支持!
这里的问题是,您从 WeekChooserBlock.get_api_representation返回
。这里的 {'ingredients':value.ingredient}
value.ingredient
是一个StreamValue实例,它是一个复杂的特定于Wagtail的对象,包含用于模板渲染的方法以及实际的流数据-DRF不知道如何来处理这个复杂的对象。
您需要确保 get_api_representation
响应仅包含标准Python类型,例如作为字符串和字典。例如:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self,value,context = None):
如果值:
返回{
'ingredients':[ingredient.value ['name'] for value in value.ingredient],
}
如果要重复使用 IngredientChooserBlock.get_api_representation $ c中定义的配料的API表示, $ c>,这有点麻烦,但是您应该可以使用以下方法做到这一点:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self,value,context = None):
如果值:
成分=值。成分
返回成分.stream_block.get_api_representation(成分,上下文=上下文)
Previous topic where I was kindly helped by @gasmanso i have a model class ingredients like:
@register_model_chooser
class Ingredient(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
and to represent this in API i created this class:
class IngredientChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'name': value.name,
}
then i have another model class that uses IngredientChooserBlock
class:
@register_model_chooser
class Menu(models.Model):
ingredient = StreamField([
('zutaten', IngredientChooserBlock('kitchen.Ingredient')) ],
null=True, verbose_name='', blank=True)
def __str__(self):
return self.title
and because i need this ingredient
in my API i created same model class to overwrite get_api_representation
:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'ingredients': value.ingredient,
}
and in the end in my main model class I'm trying to use this WeekChooserBlock
which takes kitchen.Menu
as argument like so:
class Week(models.Model):
dishes_sp = StreamField([
('menu', WeekChooserBlock('kitchen.Menu')) ],
null=True, verbose_name='', blank=True)
The problem is that it prints out an error in DRF like this:
Object of type 'StreamValue' is not JSON serializable
Didn't want to create too big question, but for greater clarity i have actually another objects in my Menu
class like:
class Menu(models.Model):
title = models.CharField(max_length=255)
image = models.URLField(blank=True, null=True)
price = models.FloatField(blank=True, null=True, max_length=255)
ingredient = StreamField([
('zutaten', IngredientChooserBlock('kitchen.Ingredient')) ],
null=True, verbose_name='', blank=True)
steps = StreamField([
('Schritt', TextBlock())
], null=True, verbose_name='Vorbereitungsschritte', blank=True)
and I'm also trying to represent them too. But the error is displayed only if I'm trying to output StreamField
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'title': value.title,
'picture': value.image,
'price': value.price,
'ingredients': value.ingredient,
'steps': value.steps
}
Thanks for your support!
The problem here is that you're returning {'ingredients': value.ingredient}
from WeekChooserBlock.get_api_representation
. Here value.ingredient
is a StreamValue instance, which is a complex Wagtail-specific object containing methods for template rendering, as well as the actual stream data - DRF doesn't know how to handle this complex object.
You need to ensure that your get_api_representation
response only consists of standard Python types, such as strings and dicts. For example:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'ingredients': [ingredient.value['name'] for ingredient in value.ingredient],
}
If you want to re-use the API representation for Ingredient that you defined in IngredientChooserBlock.get_api_representation
, it gets a bit tricker, but you should be able to do this with:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
ingredient = value.ingredient
return ingredient.stream_block.get_api_representation(ingredient, context=context)
这篇关于将类对象转换为get_api_representation函数的可读值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!