Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python django REST框架多源字段_Python_Django_Serialization_Field_Django Rest Framework - Fatal编程技术网

Python django REST框架多源字段

Python django REST框架多源字段,python,django,serialization,field,django-rest-framework,Python,Django,Serialization,Field,Django Rest Framework,假设我的模型中有这些。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) c

假设我的模型中有这些。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中使用主题。
为此,我需要序列化它:

#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")
不幸的是,我无法使用级别集源,因为它不存在。

如何将puzzlelevel\u集imageandwordlevel\u集组合到一个levels字段中?

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

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",)
我做这件事是因为

student = StudentSerializer(source="from_person") or 
          StudentSerializer(source="to_person")
谢谢

您可以使用MethodFiel(DRF=3.x)
没有测试它

field\u to\u native()
方法已在DRF 3.0中删除
serializers.SerializerMethodField()
    levels = serializers.SerializerMethodField()

    def get_levels(self, obj):
        value = []
        s1 = PuzzleLevelSerializer(obj, many=True, source="puzzlelevel_set")
        s2 = ImageAndWordLevelSerializer(obj, many=True, source="imageandwordlevel_set")

        value.extend(s1.data)
        value.extend(s2.data)
        return value