django db クエリの最適化に関する初心者の質問:
Destination オブジェクトを編集するためのカスタム モデル フォームがあり、コンストラクターで、関連する Visitor モデルからクエリセットを取得します。このモデルには、Destination に ManyToMany フィールドがあります (カスタム モデル フォームを使用する理由については、EDIT を参照してください)。
print "loading initial choices"
visitor_choices, visitor_initial = [], []
visitor_set = self.instance.visitor_set.all()
print visitor_set
for obj in Visitor.objects.all():
visitor_choices.append((obj.pk, obj.name))
#if visitor_set.filter(pk=obj.pk # this hits the db every time!
if obj in visitor_set:
visitor_initial.append(obj.pk)
self.fields['visitors'].choices = visitor_choices
self.fields['visitors'].initial = visitor_initial
print "finished loading initial choices"
アイデアは、関連する Visitor_set を変数にロードして、各訪問者が Visitor_set に存在するかどうかを確認するためのクエリの繰り返しを避けることでした。これは最善のアプローチですか?
また、データベース ロギングをオンにすると (この質問の 2 番目の回答で説明されているように)、目的地 ID 1 のすべての訪問者を選択するクエリ (3 番目の SELECT ステートメント) が繰り返されるのがわかりますが、これは私が書いたコードのどこにもありません。それはどこから来たのですか?
loading initial choices
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testapp_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 LIMIT 21; args=(1,
)
[<Visitor: MIMA>, <Visitor: MIMO>, <Visitor: MIMU>]
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor"; args=()
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testapp_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 ; args=(1,)
finished loading initial choices
編集
Destination
私が参照するオブジェクトは、オブジェクトのフィールドの関連する側ManyToMany
ですVisitor
。私のフォームが Visitor オブジェクト自体を編集していた場合、Django はManyToMany
フィールドを自動的に処理します。しかし、モデル フォームでこれを行うにはDestination
、複数選択フィールドをVisitor
追加し、メソッドをカスタマイズし__init__
て選択肢と初期選択をロードする必要があります。
ただし、質問はクエリセットの処理方法と、シェルからも確認できる manytomany 値をロードするための不思議な 2 番目の SQL に関するものです。
>>> from testapp.forms import DestinationForm
>>> from testapp.models import Destination, Visitor
>>> dest = Destination.objects.get(pk=1)
(0.001) SELECT "testapp_destination"."id", "testapp_destination"."destination" FROM "testapp_destination" WHERE "testapp_destination"."id" =
1 ; args=(1,)
>>> destinationForm = DestinationForm(instance=dest)
loading initial choices
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testap
p_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 LIMIT 21; args=(1,
)
[<Visitor: MIMA>, <Visitor: MIMO>, <Visitor: MIMU>]
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor"; args=()
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testap
p_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 ; args=(1,)
finished loading initial choices
>>>
ありがとう