我目前正在尝试提高服务器的性能,而且我已经用了几天工作,到目前为止我还没有找到解决方案。 我使用django 1.5并且没有机会升级到更新的版本。
鉴于这些模型:
class Company(models.Model):
name = models.CharField()
class Store(models.Model):
name = models.CharField()
closed = models.BooleanField()
store = models.ForeignKey(Company)
根据文档,如果我想预取反转的外键,我可以这样做:
companies = Company.objects.filter(
name__startswith = "stackoverflow",
).prefetch_related("store_set")
for company in companies:
open_stores = company.store_set.all()
这很好用,一切都在1个查询中完成。但是,我只想要开放的商店。这样做会导致额外的查询:
for company in companies:
open_stores = company.store_set.filter(open = True)
所以,这根本没用。 我如何预取所有已打开的商店?
我的一个想法是做类似的事情:
class Company(models.Model):
name = models.CharField()
prefetched_stores = None
def _prefetch_stores(self):
return self.store_set.filter(closed = False)
def __init__(self, *args, **kwargs):
force_prefetch = kwargs.pop("force_prefetch" or None)
if force_prefetch:
self.prefetched_stores = self._prefetch_stores()
class Store(models.Model):
name = models.CharField()
closed = models.BooleanField()
store = models.ForeignKey(Company)
这个问题的一个问题是我并不总是想要预先加载商店,所以init不是正确的地方(并且很可能会引起一堆副作用)但我希望你能理解。
这是可能的还是我走到了死胡同?如果可能的话,我该怎么做?
答案 0 :(得分:1)
只需在python代码中过滤商店:
for company in companies:
open_stores = [s for s in company.store_set.all() if not s.closed]
或手动预取商店:
companies = Company.objects.filter(name__startswith="stackoverflow")
open_stores_d = {}
for store in Store.objects.filter(closed=False, company__in=companies):
open_stores_d.setdefault(store.company, []).append(store)
for company in companies:
open_stores = open_stores_d.get(company, [])