6

映画、本、ソフトウェアのデータベースがあり、それらすべてが単一のアイテムモデルを継承しているとします。

class Item(models.Model):
    ...

class Movie(models.Model):
    item = models.OneToOneField(Item)
    ...

class Book(models.Model):
    item = models.OneToOneField(Item)
    ...

class Software(models.Model):
    item = models.OneToOneField(Item)
    ...

ここで、アイテムに対してデータベースクエリを実行したいのですが、映画、本、ソフトウェアのいずれであっても、そのアイテムに関連するオブジェクトを取得したいと思います。すべてのアイテムが1つのタイプ、たとえば映画の場合、次のことができます。

Item.objects.prefetch_related('movie')

ただし、タイプに関係なく、関連するオブジェクトをフェッチできる必要があります。実行できますか:

Item.objects.prefetch_related('movie', 'book', 'software')

これは、タイプに関係なく関連するオブジェクトを見つけますか?これは効率的ですか?これを行うためのより良い方法はありますか?

4

1 に答える 1

6

QuerySet の例が示すように、OneToOneFieldが設定されていると仮定します。つまり、それぞれとです。related_name'movie''book''software'

必要のない 1 対 1 の関係を逆方向にトラバースするには、によって自動生成されるprefetch_relatedを使用して簡単に実現できます。つまり、できるはずですLEFT OUTER JOINselect_related

Item.objects.select_related('movie', 'book', 'software')

返された各 Item インスタンスには、対応するMovie, Bookandのキャッシュされたインスタンスが自動的に含まれますSoftware(もちろん、存在する場合)。

prefetch_relatedは、多対多または多対 1 のリレーションシップ (つまり、ManyToManyFieldまたは逆トラバーサル) での O(N) クエリの問題を回避する場合にのみ必要ですForeignKey

于 2012-04-21T00:30:50.197 に答える