将 class 对象转换为 get_api_representation 函数的可读值
Converting class object to readable value for get_api_representation function
所以我有一个模型 class 配料如下:
@register_model_chooser
class Ingredient(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
为了在 API 中表示这一点,我创建了这个 class:
class IngredientChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'name': value.name,
}
然后我有另一个模型 class 使用 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
并且因为我在我的 API 中需要这个 ingredient
我创建了相同的模型 class 来覆盖 get_api_representation
:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'ingredients': value.ingredient,
}
最后在我的主模型中 class 我正在尝试使用这个 WeekChooserBlock
它将 kitchen.Menu
作为参数,如下所示:
class Week(models.Model):
dishes_sp = StreamField([
('menu', WeekChooserBlock('kitchen.Menu')) ],
null=True, verbose_name='', blank=True)
问题是它在 DRF 中打印出如下错误:
Object of type 'StreamValue' is not JSON serializable
不想提出太大的问题,但为了更清楚起见,我的 Menu
class 实际上还有另一个对象,例如:
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)
而且我也在努力代表他们。但仅当我尝试输出 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
}
感谢您的支持!
这里的问题是您从 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):
if value:
return {
'ingredients': [ingredient.value['name'] for ingredient in value.ingredient],
}
如果你想重新使用你在 IngredientChooserBlock.get_api_representation
中定义的成分的 API 表示,它会有点诡计,但你应该能够做到这一点:
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)
@register_model_chooser
class Ingredient(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
为了在 API 中表示这一点,我创建了这个 class:
class IngredientChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'name': value.name,
}
然后我有另一个模型 class 使用 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
并且因为我在我的 API 中需要这个 ingredient
我创建了相同的模型 class 来覆盖 get_api_representation
:
class WeekChooserBlock(ModelChooserBlock):
def get_api_representation(self, value, context=None):
if value:
return {
'ingredients': value.ingredient,
}
最后在我的主模型中 class 我正在尝试使用这个 WeekChooserBlock
它将 kitchen.Menu
作为参数,如下所示:
class Week(models.Model):
dishes_sp = StreamField([
('menu', WeekChooserBlock('kitchen.Menu')) ],
null=True, verbose_name='', blank=True)
问题是它在 DRF 中打印出如下错误:
Object of type 'StreamValue' is not JSON serializable
不想提出太大的问题,但为了更清楚起见,我的 Menu
class 实际上还有另一个对象,例如:
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)
而且我也在努力代表他们。但仅当我尝试输出 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
}
感谢您的支持!
这里的问题是您从 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):
if value:
return {
'ingredients': [ingredient.value['name'] for ingredient in value.ingredient],
}
如果你想重新使用你在 IngredientChooserBlock.get_api_representation
中定义的成分的 API 表示,它会有点诡计,但你应该能够做到这一点:
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)