Djangoでフィールド間の大小比較や差の絶対値の計算を行う
概要
Djangoでフィールド間の大小比較をした結果や,フィールド間の差の絶対値を新しいフィールドとして保存する方法について調べたので,メモを残しておきます.
使用環境
使用するモデル
今回は以下のような対戦結果を保持するモデルを使用します.
from django.db import models class Matchup(models.Model): win_player_id = models.IntegerField() win_player_rate = models.IntegerField() lose_player_id = models.IntegerField() lose_player_rate = models.IntegerField()
方法
新たなフィールドを追加する方法
QuerySetオブジェクトのannotate
メソッドを用いることで,新たなフィールドを追加(アノテーション)することができます.
このannotate
メソッドは,データの個数のカウントなどによく用いられます.
使用例
# Each publisher, each with a count of books as a "num_books" attribute. >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs <QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]> >>> pubs[0].num_books 73
参照: Aggregation | Django documentation | Django
大小比較した結果を新たなフィールドとして追加する
上で説明したannotate
メソッドと,Djangoで定義されているデータベース関数のうちの一つであるSign
を用いることで,大小比較をした結果をフィールドに追加することが可能です.
from django.db.models import F from django.db.models.functions import Sign # どちらのレートが大きいかを算出. # +1 -> win_playerの方が大きい.-1 -> lose_playerの方が小さい. # 0 -> レートが同じ matchup = Matchup.objects.all().annotate( superior=Sign(F("win_player_rate") - F("lose_player_rate")) )
このF
オブジェクトは,モデルの特定のフィールドの値を表現するものです.
上の場合だとwin_player_rateとlose_player_rateの値の差を計算し,その結果に対して正負を求めることで大小関係を取得しています.
フィールド間の差の絶対値を計算し,新たなフィールドとして追加する
こちらも同様にannotate
メソッドを使用します.
Djangoでは絶対値を計算するデータベース関数としてAbs
が定義されています.
from django.db.models import F from django.db.models.functions import Abs matchup = Matchup.objects.all().annotate( rate_diff=Abs(F("win_player_rate") - F("lose_player_rate")) )
まとめ
QeurySetオブジェクトのannotate
メソッドと,Djangoで提供されているデータベース関数を用いることで,フィールド間の大小比較や差の絶対値の計算を行うことができました.他にも色々なデータベース関数が定義されているので,様々な処理ができそうです.