[解決済み] Djangoで複数のfilter()を連鎖させる、これはバグ?
質問
私はいつも、Django で複数の filter() 呼び出しを連結することは、常に 1 回の呼び出しでそれらを集めることと同じだと考えていました。
# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)
しかし、私のコードでは、複雑なクエリセットに遭遇したことがあります。
class Inventory(models.Model):
book = models.ForeignKey(Book)
class Profile(models.Model):
user = models.OneToOneField(auth.models.User)
vacation = models.BooleanField()
country = models.CharField(max_length=30)
# Not Equivalent!
Book.objects.filter(inventory__user__profile__vacation=False).filter(inventory__user__profile__country='BR')
Book.objects.filter(inventory__user__profile__vacation=False, inventory__user__profile__country='BR')
生成されたSQLは
SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") INNER JOIN "library_inventory" T5 ON ("library_book"."id" = T5."book_id") INNER JOIN "auth_user" T6 ON (T5."user_id" = T6."id") INNER JOIN "library_profile" T7 ON (T6."id" = T7."user_id") WHERE ("library_profile"."vacation" = False AND T7."country" = BR )
SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") WHERE ("library_profile"."vacation" = False AND "library_profile"."country" = BR )
最初のクエリセットで、連鎖した
filter()
の呼び出しが Inventory モデルを 2 回結合し、2 つの条件の間に OR を作成するのに対し、2 番目のクエリセットでは 2 つの条件を AND しています。私は、最初のクエリが 2 つの条件を AND にすることを期待していました。これは期待された動作なのでしょうか、それとも Django のバグなのでしょうか?
関連する質問に対する回答 Djangoで".filter().filter()..."を使用することに不利な点はありますか? は、2つのクエリセットが等価であるべきであることを示しているようです。
どのように解決するのですか?
私の理解では、デザインによって微妙に異なるということです(確かに訂正は受け付けますが)。
filter(A, B)
はまず A に従ってフィルタリングし、次に B に従ってサブフィルタリングします。
filter(A).filter(B)
は A にマッチする行と B にマッチする別の行を返します。
ここの例を見てください。
https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
は特に。
単一の filter() 呼び出しの中のすべてが同時に適用され、これらすべての要件に一致する項目をフィルタリングします。連続したfilter()呼び出しは、さらにオブジェクトのセットを制限します。
...
<ブロッククオートこの2番目の例 (filter(A).filter(B)) では、最初のフィルタがクエリセットを (A) に制限しています。2番目のフィルタは、ブログのセットをさらに(B)に制限します。二番目のフィルターで選択されたエントリーは、一番目のフィルターのエントリーと同じかもしれませんし、そうでないかもしれません`。
関連
-
[解決済み】Djangoのクエリセットフィルタリングでnot equalを行うにはどうすればよいですか?
-
[解決済み] Djangoのバージョンを確認する方法
-
[解決済み] Django のクエリで OR フィルタを行うにはどうすればよいですか?
-
[解決済み】Djangoでnull=Trueとblank=Trueの違いは何ですか?
-
[解決済み】Django ORMのselect_relatedとprefetch_relatedの違いは何ですか?
-
[解決済み] Django の修正 管理者の複数形
-
[解決済み] DjangoとReactJSを連携させる方法とは?
-
[解決済み] シグナルハンドラは 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 store to databaseは現地時間より8時間短い?(2021-05-12更新)
-
Django ForeignKey逆引きクエリにおけるfilterと_setの効率比較
-
[解決済み] Django の管理者パスワードをリセットする方法は?
-
[解決済み] (13: Permission denied) 上流:[nginx]に接続中。
-
[解決済み] Django テンプレート内で現在の URL を取得する方法は?
-
[解決済み】Djangoでモデルインスタンスをシリアライズする方法は?
-
[解決済み] Django のモデルで電話番号を保存する最良の方法は何ですか?
-
[解決済み] models.pyでDjangoの設定変数を参照するには?
-
[解決済み] 学習に適したオープンソースのdjangoプロジェクト【非公開
-
[解決済み] ブロック %} に上書きではなく、追加することはできますか?