Django RESTフレームワークシリアライザー:逆の関係の最新のオブジェクトを表示します

Wannabeコーダー

ListAPIViewのデフォルトの動作(以下のコード)は、すべてのReportオブジェクトとネストされたLogオブジェクトをReportオブジェクトごとにシリアル化することです。レポートごとに最新のLogオブジェクトのみを表示したい場合はどうすればよいですか?どうすればそれを行うことができますか?

# models.py
class Log(models.Model):
    # ...
    report = models.ForeignKey(Report)
    timestamp = models.DateTimeField(default=datetime.datetime.now)

class Report(models.Model):
    code = models.CharField(max_length=32, unique=True)
    description = models.TextField()


# serializers.py
class LogSerializer(serializers.ModelSerializer):

    class Meta:
        model = Log

class ReportSerializer(serializers.ModelSerializer):
    log_set = LogSerializer(many=True, read_only=True)

    class Meta:
        model = Report
        fields = ('code', 'description', 'log_set')


# views.py
class ReportListView(generics.ListAPIView):

    queryset = Report.objects.all()
    serializer_class = ReportSerializer

SerializerMethodFieldを使用してこれを実行できることはわかっていますが、各Reportオブジェクトに適切なLogオブジェクトを取得するための追加のSQLクエリがあるため、これは潜在的にコストのかかる操作になる可能性があります。

class ReportSerializer(serializers.ModelSerializer):
    latest_log = serializers.SerializerMethodField()

    class Meta:
        model = Report

    def get_latest_log(self, obj):
        try:
            latest_log = Log.objects.filter(report_id=obj.id).latest('timestamp')
        except Log.DoesNotExist:
            latest_log = None
        return latest_log

1000個のレポートオブジェクトがある場合、それらすべてをレンダリングする場合は、1000個の追加クエリがあります。ページネーションを使用する以外に、これらの余分なクエリを回避するにはどうすればよいですか?誰かが私を正しい方向に向けることができますか?ありがとう!

編集:重複する可能性のあるタグに関して、マークによって提供されたリンクだけでは、私にとっては完全に画像がクリアされませんでした。Todorの答えはより明確でした。

Todor

あなたは何とか注釈を付ける必要latest_logReportQuerySet、それは余分なクエリをすることなく、シリアライザで使用できるようにします。

これを達成するための最も簡単な方法は、prefetchingすべてのlogs人によるものreportです。このアプローチの欠点は、ページlogsごとにすべてメモリにロードすることですreportreport5-10-15のようなものを手に入れれば、それほど悪くはありませんlogsこれは、50のページのreports場合、50 * 10 = 500logsロードすることを意味しますが、これは大したことではありません。logsperがもっとある場合report(たとえば100)、の追加のフィルタリングを行う必要がありますqueryset

次にいくつかのサンプルコードを示します。

  1. をプリフェッチしlogsます。

    # views.py
    class ReportListView(generics.ListAPIView):
    
        queryset = Report.objects.all()\
                    .prefetch_related(Prefetch('log_set', 
                        queryset=Log.objects.all().order_by('-timestamp'),
                        to_attr='latest_logs'
                    ))
       serializer_class = ReportSerializer
    
  2. latest_logに簡単にアクセスするためのヘルパーメソッドを作成します

    class Report(models.Model):
        #...
    
        @property
        def latest_log(self):
            if hasattr(self, 'latest_logs') and len(self.latest_logs) > 0:
                return self.latest_logs[0]
            #you can eventually implement some fallback logic here 
            #to get the latest log with a query if there is no cached latest_logs 
            return None
    
  3. 最後に、シリアライザーはプロパティを使用するだけです

    class ReportSerializer(serializers.ModelSerializer):
        latest_log = serializers.LogSerializer()
    
        class Meta:
            model = Report
    

のより高度なフィルタリングの例は、logs次のようになります。

Report.objects.all().prefetch_related(Prefetch('log_set', queryset=Log.objects.all().extra(where=[
    "`myapp_log`.`timestamp` = (\
        SELECT max(timestamp) \
        FROM `myapp_log` l2 \
        WHERE l2.report == `myapp_log`.`report`\
    )"]
    ), to_attr='latest_logs'
))

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

django restフレームワークでオブジェクトを作成するときに、ネストされたシリアライザーのシリアライザーにユーザーデータを渡します

Django RESTフレームワークのGETネストされたシリアライザーはエラーを生成します: 'RelatedManager'オブジェクトには属性がありません 'datafile_set' "

Django RESTフレームワークシリアライザーPrimaryKeyRelatedField()がGET応答にオブジェクトを追加しない

シリアライザーを使用したレストフレームワークでのAPI呼び出しのDjango1対多の関係

Django RESTフレームワーク:単純なForeignKey関係にシリアライザーを使用する

Django RESTフレームワーク、シリアライザーの深さ= 1の場合の外部キー関係のフィールドの制限

Django Rest Frameworkシリアライザーの関係:親のシリアライザーのすべての子オブジェクトのリストを取得する方法は?

シリアライザーでフィールドの属性を取得する(django restフレームワーク)

Django Rest Frameworkのビューセットとシリアライザーでリクエストオブジェクトにアクセスしますか?

Django Restフレームワーク:1つのPOSTリクエストに複数のオブジェクトを挿入します

Django RESTフレームワーク-MultiSelectField-TypeError:タイプ 'set'のオブジェクトはJSONシリアル化可能ではありません

django RESTフレームワークのシリアライザーからカスタムエラー応答を送信しますか?

Django RESTフレームワーク:ネストされたオブジェクトの最新のもののみを表示し、ネストされていないJSONとして返します

Django RESTフレームワーク:オブジェクトへのユーザーアクセスを制限する

Django RESTフレームワークのCreateAPIViewでcreate()の後に別のシリアライザーを返します

django RestフレームワークのDecimalFieldシリアライザーに選択肢を提供する方法は?

シリアライザーでの権限チェック、Django Restフレームワーク、

Django REST フレームワーク シリアライザの出力

django restフレームワークで複数のオブジェクトのリストを逆シリアル化するにはどうすればよいですか?

Django RESTフレームワーク-ネストされたシリアライザーのクエリ制限?

django-rest-frameworkシリアライザーでオブジェクトリストのリストをフラット化する方法は?

Django RESTフレームワーク:さまざまなserizalizedオブジェクトのリスト?

シリアライザーの create() メソッドを編集して、Django REST Framework でネストされたオブジェクトとの関係を作成するにはどうすればよいですか?

Django RESTフレームワークで自己との再帰的な関係をシリアル化する方法は?

django RESTフレームワークで逆ネストされたシリアライザーを取得する方法はありますか?

django RESTフレームワークで逆ネストされたシリアライザーを取得する方法はありますか?

django-rest-シリアライザー内のフレームワークアクセスフィールド

Django RestFrameworkシリアライザーの更新メソッドはオブジェクトを保存しません

Django RestFrameworkシリアライザーの更新メソッドはオブジェクトを保存しません

TOP 一覧

  1. 1

    セレンのモデルダイアログからテキストを抽出するにはどうすればよいですか?

  2. 2

    Ansibleで複数行のシェルスクリプトを実行する方法

  3. 3

    tkinterウィンドウを閉じてもPythonプログラムが終了しない

  4. 4

    Windows 10 Pro 1709を1803、1809、または1903に更新しますか?

  5. 5

    Crashlytics:コンパイラー生成とはどういう意味ですか?

  6. 6

    GoDaddyでのCKEditorとKCfinderの画像プレビュー

  7. 7

    パンダは異なる名前の列に追加します

  8. 8

    モーダルダイアログを自動的に閉じる-サーバーコードが完了したら、Googleスプレッドシートのダイアログを閉じます

  9. 9

    グラフ(.PNG)ファイルをエクスポートするZabbix

  10. 10

    Chromeウェブアプリのウェブビューの高さの問題

  11. 11

    ラベルとエントリがpythontkinterに表示されないのはなぜですか?

  12. 12

    Windows 10の起動時間:以前は20秒でしたが、現在は6〜8倍になっています

  13. 13

    mutate_allとifelseを組み合わせるにはどうすればよいですか

  14. 14

    Reactでclsxを使用する方法

  15. 15

    ネットワークグラフで、ネットワークコンポーネントにカーソルを合わせたときに、それらを強調表示するにはどうすればよいですか?

  16. 16

    テキストフィールドの値に基づいて UIslider を移動します

  17. 17

    ファイル内の2つのマーカー間のテキストを、別のファイルのテキストのセクションに置き換えるにはどうすればよいですか?

  18. 18

    MLでのデータ前処理の背後にある直感

  19. 19

    Unity:未知のスクリプトをGameObject(カスタムエディター)に動的にアタッチする方法

  20. 20

    Pythonを使用して同じ列の同じ値の間の時差を取得する方法

  21. 21

    グラフからテーブルに条件付き書式を適用するにはどうすればよいですか?

ホットタグ

アーカイブ