[解決済み] なぜ django の prefetch_related() は all() でしか動作せず、filter() では動作しないのでしょうか?
質問
このようなモデルがあるとします。
class PhotoAlbum(models.Model):
title = models.CharField(max_length=128)
author = models.CharField(max_length=128)
class Photo(models.Model):
album = models.ForeignKey('PhotoAlbum')
format = models.IntegerField()
さて、もし私がアルバムの中の写真のサブセットを効率的に見たいとしたら、次のようにします。こんな感じでやってます。
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.all()
これは2つのクエリだけで、私が期待しているものです(1つはアルバムを取得し、次に `SELECT * IN photos WHERE photoalbum_id IN ().
すべてが素晴らしいです。
しかし、もし私がこうしたら
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.filter(format=1)
そして、大量のクエリを
WHERE format = 1
! 私が何か間違ったことをしているのか、それとも django がすでにすべての写真を取得して python でフィルタリングできることに気づくほど賢くないのでしょうか?ドキュメントのどこかに、そうすることになっていると書いてあったはずなのですが......。
どのように解決するのですか?
Django 1.6 以前のバージョンでは、余分なクエリを回避することはできません。そのため
prefetch_related
の呼び出しは、その結果を効果的にキャッシュします。
a.photoset.all()
の結果をキャッシュします。しかし
a.photoset.filter(format=1)
は別のクエリセットなので、すべてのアルバムに対して余分なクエリを生成することになります。
このことは
prefetch_related
ドキュメントで説明されています。は
filter(format=1)
と同等です。
filter(spicy=True)
.
Pythonで写真をフィルタリングすることで、クエリーの数を減らすことができることに注意してください。
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = [p for p in a.photo_set.all() if p.format == 1]
Django 1.7では、Djangoに対応するために
Prefetch()
オブジェクトがあり、その挙動を制御することができます。
prefetch_related
.
from django.db.models import Prefetch
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related(
Prefetch(
"photo_set",
queryset=Photo.objects.filter(format=1),
to_attr="some_photos"
)
)
for a in someAlbums:
somePhotos = a.some_photos
の使い方の例については
Prefetch
オブジェクトの使い方については
prefetch_related
のドキュメントを参照してください。
関連
-
AttributeError: 'str' オブジェクトには 'decode' という属性がありません。
-
Djangoは、フォームを送信するときに403エラーに遭遇しました。CSRF 検証に失敗しました。
-
Djangoキャッシュの説明
-
[解決済み】DjangoのネストされたMetaクラスはどのように機能するのですか?
-
[解決済み] [Solved] カスタムDjango manage.pyコマンドをテストドライバから直接呼び出すにはどうしたらいいですか?
-
[解決済み] Django ORM のクエリセットに対応する SQL クエリを表示するには?
-
[解決済み] DjangoとReactJSを連携させる方法とは?
-
[解決済み] Docker-Compose使用時にDjangoデータベースのマイグレーションをどのように行うか?
-
[解決済み] 学習に適したオープンソースのdjangoプロジェクト【非公開
-
[解決済み] django のユニットテストを複数のファイルに分散させるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Djangoは、フォームを送信するときに403エラーに遭遇しました。CSRF 検証に失敗しました。
-
django のクエリセット操作
-
Djangoキャッシュの説明
-
[解決済み] Django のフォームで、あるフィールドを編集できないように readonly (または disabled) にするにはどうしたらいいですか?
-
[解決済み] Django テンプレート内で現在の URL を取得する方法は?
-
[解決済み] djangoでurls.pyから直接名前付きurlパターンにリダイレクトする?
-
[解決済み] django-tastypie と djangorestframework の違いは何ですか?[クローズド]
-
[解決済み] Djangoで複数のfilter()を連鎖させる、これはバグ?
-
[解決済み] Django の {% url %} テンプレートタグでクエリパラメータを渡すことは可能でしょうか?
-
[解決済み] Django: Django のアプリを完全にアンインストールするには?