1. ホーム
  2. django

[解決済み] Django Rest Frameworkでネストされたシリアライザーをどのようにフィルタリングしますか?

2022-11-23 16:52:53

質問

Django Rest Framework において、シリアライザが他のシリアライザにネストされている場合、どのようにフィルタリングするのでしょうか?

私のフィルタは DRF のビューセットで課されますが、他のシリアライザ内部からシリアライザを呼び出すと、ネストしたシリアライザのビューセットは決して呼び出されないので、ネストした結果はフィルタリングされずに表示されます。

元のビューセットにフィルターを追加してみましたが、ネストされた結果は別のプリフライトされたクエリーとして呼び出されるため、ネストされた結果をフィルターすることはできないようです。(ネストされたシリアライザーは逆引きですからね)。

ネストされたシリアライザ自体に get_queryset() オーバーライドを追加して (ビューセットの外に移動して)、そこにフィルタを追加することは可能でしょうか。私もそれを試しましたが、うまくいきませんでした。

これは私が試したものですが、呼び出されることさえないようです。

class QuestionnaireSerializer(serializers.ModelSerializer):
    edition = EditionSerializer(read_only=True)
    company = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Questionnaire

    def get_queryset(self):
        query = super(QuestionnaireSerializer, self).get_queryset(instance)
        if not self.request.user.is_staff:
            query = query.filter(user=self.request.user, edition__hide=False)
        return query

どのように解決するのですか?

をサブクラス化することで リストシリアライザ を上書きし to_representation メソッドを上書きします。

デフォルトでは to_representation メソッドは data.all() をネストされたクエリセット上で呼び出します。ですから、事実上 data = data.filter(**your_filters) を作る必要があります。それから、ネストされたシリアライザのメタ上に list_serializer_class としてサブクラス化された ListSerializer を追加する必要があります。

  1. サブクラスListSerializerを上書きします。 to_representation を書き、スーパー
  2. サブクラス化されたListSerializerをメタとして追加します。 list_serializer_class をネストされたSerializerの上に追加します。

以下は、サンプルに関連するコードです。

class FilteredListSerializer(serializers.ListSerializer):

    def to_representation(self, data):
        data = data.filter(user=self.context['request'].user, edition__hide=False)
        return super(FilteredListSerializer, self).to_representation(data)


class EditionSerializer(serializers.ModelSerializer):

    class Meta:
        list_serializer_class = FilteredListSerializer
        model = Edition


class QuestionnaireSerializer(serializers.ModelSerializer):
    edition = EditionSerializer(read_only=True)
    company = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Questionnaire