2014-11-06 78 views
2

比方說,我在models.py有這些:Django的REST框架多源字段

#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") 

Unfortunaly,因爲它不存在,我無法使用level_set源。
我怎麼能在一個單一的水平場結合puzzlelevel_setimageandwordlevel_set

回答

1

其實,在深入瞭解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",) 
0

我這樣做是

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

感謝