将 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)