型号:
class ItemManager(models.Manager):
def get_queryset(self):
return super(AssetsManager, self).get_queryset().prefetch_related(
models.Prefetch("assignments", queryset=Assignments.objects.select_related("userid")))
class Item(models.Model):
objects = ItemManager()
id = UnsignedAutoField(db_column='Id', primary_key=True)
user = models.ManyToManyField('Owner', through='Assignments', through_fields=('itemid', 'userid'))
@property
def owner(self):
return self.assignments.select_related("userid").last().userid
class User(models.Model):
id = UnsignedAutoField(db_column='Id', primary_key=True)
item = models.ManyToManyField('Item', through='Assignments', through_fields=('userid', 'itemid'))
class Assignments(models.Model):
id = UnsignedAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
userid = models.ForeignKey('User', default=None, blank=True, null=True, on_delete=models.SET_DEFAULT)
itemid = models.ForeignKey('Item', on_delete=models.SET_DEFAULT, related_name='assignments')
在我的模板中,我尝试遍历Item
查询集,同时显示owner
。问题在于,将对循环的每个步骤进行一次新的SQL查询。
模板循环:
{% if item_list %}
{% for item in item_list %}
{{item}} - {{item.owner}}
{% endfor %}
{% endif %}
该视图是ListView
,其中查询集为“ Item.objects.filter(Q(id__gte = 1)&Q(id__lte = 5))”。 context_object_name
是item_list
。
使用Django调试工具栏,我注意到以下内容:
SELECT ••• FROM `Assignments` LEFT OUTER JOIN `User` ON (`Assignments`.`UserId` = `User`.`Id`) WHERE `Assignments`.`ItemId` IN (1, 3, 5, 2, 4)
此查询对应于{% if item_list %}
然后针对每次迭代进行新查询:
SELECT ••• FROM `Assignments` LEFT OUTER JOIN `User` ON (`Assignments`.`UserId` = `User`.`Id`) WHERE `Assignments`.`ItemId` = 1 ORDER BY `Assignments`.`id` DESC LIMIT 1
对应于{{item}} - {{item.owner}}
。
以上示例是我为测试所做的简化。我实际上在django-tables2中遇到了这个问题。
我尝试过使用prefetch_related,不同组合的Prefetch对象来进行各种查询集,但从未使用过。每次将新查询发送到数据库。
有没有优化此迭代的方法?