12

問題

次の標準的な一般的な外部キーフィールドを持つモデルがあります。

content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
event_object = generic.GenericForeignKey('content_type', 'object_id')

RESTフレームワークのドキュメントによると、これを正しくシリアル化するために次のことができます。

class WhateverSerializer(serializers.ModelSerializer):
    event_object = serializers.RelatedField(source='event_object')

これは正常に機能しますが、他の2つの関連する状況では、動作させることができません。

  1. 使いたいHyperlinkedRelatedFieldです。このフィールドにはview_name引数が必要です。これは、ビュー名が関連するモデルによって異なるため、宣言できません。SerializerMethodFieldを使用して、実行時にインスタンス化し、HyperlinkedIdentityFieldそのメソッドを返すことでこれを解決しましたfield_to_native(以下のスニペットを参照)。これはあまりエレガントではありません。
  2. と言って、関連するオブジェクトをシリアル化に直接ネストしたいと思いますevent_object = SoAndSoSerializer(source='event_object')。私が見ることができる唯一の解決策は、*Serializer私が定義したすべてを歩き、正しいモデルを持っているものを確認し、それを使用することです。繰り返しますが、これはあまりエレガントではありません。

質問

HyperlinkRelatedFieldは、一般的な関係全体で機能することを目的としていますか?私はただ間違えているのですか?*Serializer私が欠けている権利を選ぶための明白な解決策はありますか?

コードスニペット

上記の箇条書き1で述べたエレガントでない解決策:

class WhateverSerializer(DefaultSerializer):

    event_object_url = serializers.SerializerMethodField('get_related_object_url')
    # ...

    def get_related_object_url(self, obj):
        obj = obj.event_object
        default_view_name = '%(model_name)s-detail'
        format_kwargs = {
            'app_label': obj._meta.app_label,
            'model_name': obj._meta.object_name.lower()
        }
        view_name = default_view_name % format_kwargs
        s = serializers.HyperlinkedIdentityField(source=obj, view_name=view_name)
        s.initialize(self, None)
        return s.field_to_native(obj, None)
4

1 に答える 1

8

あなたの権利、RESTフレームワークはそれらのユースケースをサポートしておらず、サポートした場合のデザインがどのようになるかは私にはわかりません。おそらく、model-> view(ハイパーリンクの場合)とmodel-> serializer(ネストされた場合)の暗黙のレジストリが必要になるでしょうが、私はあまり熱心ではないと思います。

必要なことを行う最も簡単な方法は、おそらくサブクラスManyRelatedField化してカスタムフィールドタイプを作成to_native(self, obj)し、セット内の各オブジェクトを希望どおりにシリアル化するようにオーバーライドすることです。

于 2013-01-22T08:48:48.463 に答える