順参照ー逆参照の組合せ
順参照は select_related (INNER JOIN), 逆参照は prefetch_related (2 つの SQL クエリーをメモリ内で Django が連結) で対応するわけだが、組み合わせたいときはそのパターンによって書き方がある。
以下のサイトで色々な組合せが書いてあるが
Django ORM にて SQL発行数を抑えながら順参照、逆参照する方法
順参照-逆参照のパターンが無かったのでここに記す。
prefetch_related("foo__bar_set")
上記の書き方をすると、その後のコードでは foo__bar_set.all() という使い方しかできない。foo__bar_set.filter(hoge=fuga) 等のように filter を使うと上記プリフェッチは無効になる。
もし filter を使うのなら to_attr でフィールドに格納するのだが、その場合は foo を経由して呼び出すことになる。
例えば上記サイトのモデルをベースに、Department への順参照をする Asset というモデル (Asset の FK として department_id ) があるとする。
employees = Employee.objects.all().prefetch_related( "department__asset_set", queryset=Asset.objects.filter(name__icontains="テスト"), to_attr="assets" )
こうした場合、assets には Asset のインスタンスの list が格納されている。(queryset ではない)
このインスタンスの list を呼び出すには
for employee in employees: my_asset_list = employee.department.assets
と department を経由して assets を呼び出す。
コメント