すでに投稿された回答を確認します。実際の例で答えを追加した方がいいと思いました。
関連する3つのDjangoモデルがあるとします。
class M1(models.Model):
name = models.CharField(max_length=10)
class M2(models.Model):
name = models.CharField(max_length=10)
select_relation = models.ForeignKey(M1, on_delete=models.CASCADE)
prefetch_relation = models.ManyToManyField(to='M3')
class M3(models.Model):
name = models.CharField(max_length=10)
ここでは、問い合わせることができM2モデルとその相対的なM1使用してオブジェクトをselect_relationフィールドとM3使用してオブジェクトをprefetch_relationフィールド。
ただし、M1のリレーションはM2isであるForeignKeyことを説明したように、オブジェクトのレコードは1つだけ返されM2ます。同じことが当てはまりOneToOneFieldます。
しかし、M3の関係はでM2あり、ManyToManyField任意の数のM1オブジェクトを返す可能性があります。
2つのM2オブジェクトがありm21、ID m22が同じ5つのM3オブジェクトが関連付けられている場合を考えます1,2,3,4,5。M3これらの各オブジェクトに関連付けられたオブジェクトをフェッチするときにM2、select relatedを使用すると、これが動作します。
手順:
m21オブジェクトを検索します。
- IDがである
M3オブジェクトに関連するすべてのオブジェクトを照会しm21ます1,2,3,4,5。
m22オブジェクトと他のすべてのM2オブジェクトについて同じことを繰り返します。
私たちは同じ持っているように1,2,3,4,5、両方のIDをm21、m22私たちはselect_relatedオプションを使用する場合は、オブジェクトは、すでにフェッチされた同じIDの二回DBを照会するために起こっています。
代わりに、prefetch_relatedを使用する場合、M2オブジェクトを取得しようとすると、M2テーブルのクエリ中にオブジェクトが返したすべてのID(注:IDのみ)が記録され、最後のステップとして、DjangoがM3テーブルにクエリを実行しますM2オブジェクトが返したすべてのIDのセット。M2データベースの代わりにPythonを使用してオブジェクトに結合します。
この方法では、すべてのM3オブジェクトを1回だけクエリするので、パフォーマンスが向上します。