2013-08-23 49 views
91

我想序列模型,而是要包括需要在模型實例做一些數據庫查找附加字段被序列化:Django的REST框架:增加額外的外地ModelSerializer

class FooSerializer(serializers.ModelSerializer): 
    my_field = ... # result of some database queries on the input Foo object 
    class Meta: 
     model = Foo 
     fields = ('id', 'name', 'myfield') 

什麼正確的方式來做到這一點?我在序列化程序中看到you can pass in extra "context",是傳遞上下文字典中其他字段的正確答案?通過這種方法,獲取我所需的字段的邏輯將不會與序列化程序定義保持一致,這是理想的,因爲每個序列化的實例都需要my_field。在DRF序列器文檔中的其他地方,says「額外字段可以對應於任何屬性或在模型上可調用」。額外的領域我在說什麼?我應該在Foo的模型定義中定義一個返回my_field值的函數,並且在序列化程序中,我將my_field連接到可調用的?這是什麼樣子?

在此先感謝,如有必要,請高興地澄清問題。

回答

158

我覺得SerializerMethodField是你在找什麼:

class FooSerializer(serializers.ModelSerializer): 
    my_field = serializers.SerializerMethodField('is_named_bar') 

    def is_named_bar(self, foo): 
     return foo.name == "bar" 

    class Meta: 
    model = Foo 
    fields = ('id', 'name', 'my_field') 

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

+0

+1,這對於CustomSerializer是否也適用? –

+12

是否可以向這些字段添加驗證?我的問題是:如何接受可以在post_save()處理程序中驗證和處理的自定義POST值? – Alp

+7

請注意,SerializerMethodField是隻讀的,因此這對傳入的POST/PUT/PATCH不起作用。 –

29

您可以將您的模型方法更改爲屬性,並使用此方法在序列化程序中使用它。

編輯:最近版本的rest框架(我試過3.3.3),你不需要改變屬性。模型方法將正常工作。

+0

Thanks @Wasil!我不熟悉在Django模型中使用屬性,並且找不到它的含義。你可以解釋嗎?這裏@property裝飾器的要點是什麼? – Neil

+2

這意味着你可以像調用屬性一樣調用這個方法:即'variable = model_instance.my_field'與沒有裝飾器的'variable = model_instance.my_field()'給出了相同的結果。 另外:http://stackoverflow.com/a/6618176/2198571 –

+0

這是行不通的,至少在Django 1.5.1/djangorestframework == 2.3.10。即使明確地在「字段」元屬性中引用,ModelSerializer也不會獲得該propery。 – ygneo

8

我對類似的問題(here)的反應可能是有用的。

如果你有下列方式定義的模型方法:

class MyModel(models.Model): 
    ... 

    def model_method(self): 
     return "some_calculated_result" 

您可以添加調用該方法的結果,你的串行像這樣:

class MyModelSerializer(serializers.ModelSerializer): 
    model_method_field = serializers.CharField(source='model_method') 

附:由於自定義字段是不是真的在模型中的一個字段,你通常會希望把它只讀的,就像這樣:

class Meta: 
    model = MyModel 
    read_only_fields = (
     'model_method_field', 
     ) 
7

使用Django REST框架的最後一個版本,你需要創建一個方法在您的模型中添加您要添加​​的字段的名稱。不需要@propertysource='field'引發錯誤。

class Foo(models.Model): 
    . . . 
    def foo(self): 
     return 'stuff' 
    . . . 

class FooSerializer(ModelSerializer): 
    foo = serializers.ReadOnlyField() 

    class Meta: 
     model = Foo 
     fields = ('foo',) 
相關問題