モデルをシリアル化したいが、シリアル化されるモデルインスタンスでいくつかのデータベースルックアップを行う必要がある追加フィールドを含めたい:
class FooSerializer(serializers.ModelSerializer):
my_field = ... # result of some database queries on the input Foo object
class Meta:
model = Foo
fields = ('id', 'name', 'myfield')
これを行う正しい方法は何ですか? 余分な「コンテキスト」で渡すことができます シリアライザに、コンテキスト辞書の追加フィールドに渡す正しい答えですか?このアプローチでは、必要なフィールドを取得するロジックはシリアライザーの定義と独立していません。これは、すべてのシリアル化されたインスタンスにmy_field
が必要なため理想的です。 DRFシリアライザーのドキュメントの他の場所では、それは says 「追加のフィールドは、モデル上の任意のプロパティまたは呼び出し可能オブジェクトに対応できます」。私が話しているのは余分なフィールドですか? my_field
値を返すFoo
のモデル定義で関数を定義し、シリアライザーでmy_fieldをその呼び出し可能オブジェクトに接続する必要がありますか?それはどのように見えますか?
事前に感謝し、必要に応じて質問を明確にします。
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
モデルメソッドをプロパティに変更し、このアプローチでシリアライザーで使用できます。
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
class FooSerializer(ModelSerializer):
my_field = serializers.ReadOnlyField(source='my_field')
class Meta:
model = Foo
fields = ('my_field',)
編集:レストフレームワークの最新バージョン(3.3.3を試しました)では、プロパティに変更する必要はありません。モデルメソッドは正常に機能します。
Django Rest Frameworkの最新バージョンでは、追加するフィールドの名前を使用してモデルにメソッドを作成する必要があります。 @property
およびsource='field'
が不要なため、エラーが発生します。
class Foo(models.Model):
. . .
def foo(self):
return 'stuff'
. . .
class FooSerializer(ModelSerializer):
foo = serializers.ReadOnlyField()
class Meta:
model = Foo
fields = ('foo',)
同様の質問に対する私の回答( 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',
)
余分なフィールドで読み取りと書き込みが必要な場合は、serializers.Serializerを拡張する新しいカスタムシリアライザーを使用して、次のように使用できます。
class ExtraFieldSerializer(serializers.Serializer):
def to_representation(self, instance):
# this would have the same as body as in a SerializerMethodField
return 'my logic here'
def to_internal_value(self, data):
# This must return a dictionary that will be used to
# update the caller's validation data, i.e. if the result
# produced should just be set back into the field that this
# serializer is set to, return the following:
return {
self.field_name: 'Any python object made with data: %s' % data
}
class MyModelSerializer(serializers.ModelSerializer):
my_extra_field = ExtraFieldSerializer(source='*')
class Meta:
model = MyModel
fields = ['id', 'my_extra_field']
いくつかのカスタムロジックで関連するネストされたフィールドでこれを使用します
これは私のために働いた。ルックアップの計算後、フィールドにvalを割り当てることができます。または、APIレスポンスでパラメーターを送信する場合もあります。
Model.pyで
class Foo(models.Model):
"""Model Foo"""
name = models.CharField(max_length=30, help_text="Customer Name")
**
Serializer.pyで
**
class FooSerializer(serializers.ModelSerializer):
retrieved_time = serializers.SerializerMethodField()
@classmethod
def get_retrieved_time(self, object):
"""getter method to add field retrieved_time"""
return None
class Meta:
model = Foo
fields = ('id', 'name', 'retrieved_time ')
**
これが誰かを助けることを願っています
**
Chemical Programer で このコメント で述べたように、最新のDRFでは次のようにできます:
class FooSerializer(serializers.ModelSerializer):
extra_field = serializers.SerializerMethodField()
def get_extra_field(self, foo_instance):
return foo_instance.a + foo_instance.b
class Meta:
model = Foo
fields = ('extra_field', ...)