python - django REST framework 多源字段

标签 python django serialization field django-rest-framework

假设我的 models.py 中有这些:

#models.py
class Theme(models.Model):
    """An theme is an asset of multiple levels."""

    adventure = models.ForeignKey(Adventure)
    offset = models.PositiveSmallIntegerField()
    finished = models.BooleanField(default=False)

class Level(models.Model):
    """Abstract level representation"""

    theme = models.ForeignKey(Theme)
    offset = models.PositiveSmallIntegerField()
    finished = models.BooleanField(default=False)

    class Meta:
        abstract = True

class PuzzleLevel(Level):
    """A level for the Puzzle game"""

    points = models.CharField(max_length=200)
    image = models.ImageField()

class ImageAndWordLevel(Level):
    """A level for the ImageAndWord game"""

    word = models.CharField(max_length=30)
    image = models.ImageField()

我想在我的 api 中使用 Theme。
为此,我需要对其进行序列化:

#serializers.py
class PuzzleLevelSerializer(serializers.ModelSerializer):
    image = serializers.Field(source="image.url")

    class Meta:
        model = PuzzleLevel
        fields = ("offset", "finished", "points", "image")

class ImageAndWordLevelSerializer(serializers.ModelSerializer):
    image = serializers.Field(source="image.url")

    class Meta:
        model = ImageAndWordLevel
        fields = ("offset", "finished", "word", "image")

class ThemeSerializer(serializers.ModelSerializer):
    levels = serializers.Field(source="level_set")

    class Meta:
        model = Theme
        fields = ("offset", "finished", "levels")

不幸的是,我无法使用 level_set 源,因为它不存在。
我如何将 puzzlelevel_setimageandwordlevel_set 组合到一个levels 字段中?

最佳答案

实际上,在深入研究 REST framework 的源代码之后,我得出了一个解决方案:
我编写了一个能够管理多个来源的自定义字段。

class MultiSourceField(serializers.Field):
    """
    A custom field to use when you want to
    join multiple sources into a single field.
    Example :
        my_field = MultiSourceField(source=["attr1.subattr", "attr2.subattr"])
    It can also handle serializers, a small example :
        rel_field = MultiSourceField(source=[Serializer(source="rel"), "attr2"])
    """

    def field_to_native(self, obj, field_name):
        if obj is None:
            return self.empty

        sources = self.source
        value = []
        for source in sources:
            if isinstance(source, serializers.BaseSerializer):
                value += source.field_to_native(obj, "")
            else:
                #setting self.source to source in order to use the parent method
                self.source = source
                value.append(super(MultiSourceField, self).field_to_native(obj,
                    field_name))
                #reverting self.source after the parent method call
                self.source = sources
        return value

现在,我的主题序列化器看起来像这样:

class ThemeSerializer(serializers.ModelSerializer):
    levels = MultiSourceField(source=[
        PuzzleLevelSerializer(source="puzzlelevel_set"),
        ImageAndWordLevelSerializer(source="imageandwordlevel_set")
    ])

    class Meta:
        model = Theme
        fields = ("offset", "finished", "levels",)

关于python - django REST framework 多源字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26782993/

相关文章:

python - 为什么我得到 "ق"而不是 "fi"?

python - TransactionManagementError "You can' t 在使用信号时执行查询直到 'atomic' block 结束,但仅在单元测试期间

python - 猴子在另一个应用程序中修补 Django 应用程序

python - 尝试使用elasticsearch-dsl Python软件包访问Elasticsearch Cloud时的“Failed to establish a new connection”

java - 不确定如何在从 ObjectInputStream() 加载后显示对象

python - 如何使用 pandas 根据行和列名称创建数组

Python - 日期时间时间始终为零

python - Pandas 数据帧,ValueError : shape mismatch: objects cannot be broadcast to a single shape

Azure 服务总线队列 - 使用 BrokeredMessage 进行序列化

javascript - 如何使用 openlayers 3 将图层上的所有功能序列化为 json