Python django REST框架多源字段
假设我的模型中有这些。py: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
#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