1. ホーム
  2. ジャンゴ

[解決済み] Django restフレームワーク、同じModelViewSetで異なるシリアライザーを使用する。

2022-04-16 04:58:51

質問

2つの異なるシリアライザを提供したいのですが、同時に ModelViewSet :

  • オブジェクトのリストを表示するとき、各オブジェクトにその詳細へリダイレクトするURLを持たせ、他のすべての関連は __unicode __ をターゲットモデルの

の例です。

{
  "url": "http://127.0.0.1:8000/database/gruppi/2/",
  "nome": "universitari",
  "descrizione": "unitn!",
  "creatore": "emilio",
  "accesso": "CHI",
  "membri": [
    "emilio",
    "michele",
    "luisa",
    "ivan",
    "saverio"
  ]
}

  • オブジェクトの詳細を表示する際に、デフォルトの HyperlinkedModelSerializer

の例です。

{
  "url": "http://127.0.0.1:8000/database/gruppi/2/",
  "nome": "universitari",
  "descrizione": "unitn!",
  "creatore": "http://127.0.0.1:8000/database/utenti/3/",
  "accesso": "CHI",
  "membri": [
    "http://127.0.0.1:8000/database/utenti/3/",
    "http://127.0.0.1:8000/database/utenti/4/",
    "http://127.0.0.1:8000/database/utenti/5/",
    "http://127.0.0.1:8000/database/utenti/6/",
    "http://127.0.0.1:8000/database/utenti/7/"
  ]
}

以下の方法で、なんとかすべて思い通りに動作させることができました。

シリアライザー.py

# serializer to use when showing a list
class ListaGruppi(serializers.HyperlinkedModelSerializer):
    membri = serializers.RelatedField(many = True)
    creatore = serializers.RelatedField(many = False)

    class Meta:
        model = models.Gruppi

# serializer to use when showing the details
class DettaglioGruppi(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Gruppi

views.py

class DualSerializerViewSet(viewsets.ModelViewSet):
    """
    ViewSet providing different serializers for list and detail views.

    Use list_serializer and detail_serializer to provide them
    """
    def list(self, *args, **kwargs):
        self.serializer_class = self.list_serializer
        return viewsets.ModelViewSet.list(self, *args, **kwargs)

    def retrieve(self, *args, **kwargs):
        self.serializer_class = self.detail_serializer
        return viewsets.ModelViewSet.retrieve(self, *args, **kwargs)

class GruppiViewSet(DualSerializerViewSet):
    model = models.Gruppi
    list_serializer = serializers.ListaGruppi
    detail_serializer = serializers.DettaglioGruppi

    # etc.

基本的には、ユーザーがリストビューと詳細ビューのどちらを要求しているかを検出し、その要求に応じて serializer_class を自分のニーズに合わせて変更します。でも、このコードにはあまり満足していません。汚いハックのように見えますし、何より 2人のユーザーがリストと詳細を同時にリクエストした場合はどうなりますか?

を使用してこれを実現する良い方法はありますか? ModelViewSets を使用しなければならないのでしょうか? GenericAPIView ?

EDITです。

カスタムベースを使ったやり方は以下の通りです。 ModelViewSet :

class MultiSerializerViewSet(viewsets.ModelViewSet):
    serializers = { 
        'default': None,
    }

    def get_serializer_class(self):
            return self.serializers.get(self.action,
                        self.serializers['default'])

class GruppiViewSet(MultiSerializerViewSet):
    model = models.Gruppi

    serializers = {
        'list':    serializers.ListaGruppi,
        'detail':  serializers.DettaglioGruppi,
        # etc.
    }

解決方法は?

をオーバーライドして get_serializer_class メソッドを使用します。このメソッドは、適切なシリアライザークラスを取得するために、モデルミキシンで使用されます。

また get_serializer を返すメソッドです。 インスタンス 正しいシリアライザの

class DualSerializerViewSet(viewsets.ModelViewSet):
    def get_serializer_class(self):
        if self.action == 'list':
            return serializers.ListaGruppi
        if self.action == 'retrieve':
            return serializers.DettaglioGruppi
        return serializers.Default # I dont' know what you want for create/destroy/update.