本文介绍了将类对象转换为get_api_representation函数的可读值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述






不想创建太大的问题,但是为了更加清晰起见,我实际上在我的 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 ,这有点麻烦,但是您应该可以使用以下方法做到这一点:

  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函数的可读值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 12:56