0

Django Rest Frameworks を使用して API を作成しています。API はクライアントのリストを取得します。クライアントには多くのプロジェクトがあります。私のAPIは、完了したプロジェクト、保留中のプロジェクト、および合計の数を含むクライアントのリストを返す必要があります。API は機能しますが、SQL クエリが多すぎます。APIはページ分割されています

class ClientViewSet(ModelViewSet):
    """
     A simple view for creating clients, updating and retrieving
    """
    model = Client
    queryset = Client.objects.all()
    serializer_class = ClientSerializer

今、私のクライアントシリアライザー


class ClientSerializer(serializers.ModelSerializer):
    total_projects_count = serializers.SerializerMethodField()
    on_going_projects_count = serializers.SerializerMethodField()
    completed_projects_count = serializers.SerializerMethodField()

    class Meta:
        model = Client
        fields  = __all__

    def get_total_projects_count(self, obj):
        return obj.total_projects_count()

    def get_on_going_projects_count(self, obj):
        return obj.on_going_project_count()

    def get_completed_projects_count(self, obj):
        return obj.completed_projects_count()

プロジェクトにはクライアントの外部キーがあります。annotate を使用して、以下のようなすべての製品を取得し、グループ化しようとしました。しかし、注釈は単一のフィールドでしか機能しませんでした。

projects = Project.objects.filter(client__in=queryset).values('client', 'status')

複数のフィールドでグループ化し、その追加の引数をシリアライザーに渡す方法。または、より良いアプローチがあります。prefetch_related も試しましたが、 total_projects_count はまだ新しい SQL クエリを実行していました

4

2 に答える 2

0

クエリセットの計算フィールドに注釈を付けてから、メソッドを呼び出す代わりに、注釈付きの列を使用して関連する結果を返す必要があります。これにより、単一のクエリを使用してすべてのデータが取得されるようになり、確実に高速になります。

  1. クエリセットを更新します。
class ClientViewSet(ModelViewSet):
    """
     A simple view for creating clients, updating and retrieving
    """
    model = Client
    queryset = Client.objects.annotate(total_projects_count_val=...)
    serializer_class = ClientSerializer
  1. 次に、シリアライザーで、注釈付きの列を使用します
class ClientSerializer(serializers.ModelSerializer):
    total_projects_count = serializers.SerializerMethodField()
    on_going_projects_count = serializers.SerializerMethodField()
    completed_projects_count = serializers.SerializerMethodField()

    class Meta:
        model = Client
        fields  = __all__

    def get_total_projects_count(self, obj):
        return obj.total_projects_count_val

    ...

Case-Whenメソッド名を見ると、アノテーションが必要だと思います。

于 2021-02-25T20:13:53.977 に答える