191

モデルをシリアライズしたいのですが、シリアライズするモデル インスタンスでデータベース ルックアップを実行する必要があるフィールドを追加したいと考えています。

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シリアライザーのドキュメントの他の場所では、追加のフィールドは、モデルの任意のプロパティまたは呼び出し可能に対応できます」と書かれています。私が話しているのは「追加フィールド」ですか?

Fooのモデル定義で値を返す関数を定義my_fieldし、シリアライザーで my_field をその callable に接続する必要がありますか? それはどのように見えますか?

必要に応じて質問を明確にしてください。

4

9 に答える 9

287

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

于 2013-08-25T06:02:58.800 に答える
52

モデル メソッドをプロパティに変更し、このアプローチでシリアライザーで使用できます。

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を試しました)では、プロパティに変更する必要はありません。モデルメソッドは問題なく機能します。

于 2013-08-23T06:51:31.683 に答える
15

余分なフィールドで読み取りと書き込みが必要な場合は、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']

関連するネストされたフィールドでこれを使用し、いくつかのカスタム ロジックを使用します。

于 2018-05-10T10:56:25.380 に答える