我有动物和笼子。
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Cage(models.Model):
...
class Animal(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
...
首先是模型Cage。我正在尝试优化迭代Cage列表时所做的查询次数。
然后我们有模型Animal。动物包含GenericForeignKey。 Animal指出的众多物品中的一个可以是一个笼子,但也可以是其他物品,比如说食物。
如果我想获得Cage 16中的所有Animal对象,那将很容易。声明如下:
Animal.objects.filter(content_type=ContentType.objects.get_for_model(Cage), object_id=16)
因此,我可以通过以下方式获取每只笼子中的动物:
cage_content_type_id = ContentType.objects.get_for_model(Cage).id
animals_in_cage = {}
for cage in cages:
animals_in_cage[cage.id] = Animal.objects.filter(
content_type_id=cage_content_type_id,
object_id=cage.id
)
此代码的问题在于它将O(n)
SQL查询n = len(cages)
。理想情况下,我可以使用prefetch_related
之类的东西提前在动物和笼子表上进行连接。但是,我无法通过GenericForeignKeys向相反方向移动来找出任何方法。基本上我想做的是:
cages = Cage.objects.prefetch_related('animal').all()
但是动物不是Cage对象的属性,在这种情况下,cage不是Animal对象的属性。两者之间的链接是Animal模型中的内容类型和对象ID,对于某些实例,它代表一个笼子。
对于如何实现这一点的任何想法将不胜感激!
答案 0 :(得分:1)
如果凯奇有这样的事情:
animals = GenericRelation(Animal)
你可以去:
Cage.objects.filter(...).prefetch_related('animals').all()
(至少在Django 1.8.4中。)