Django - 按需调用模型的方法从反向外键过滤和预取数据
Django - Call model's method on demand to filter and prefetch data from a reversed foreignkey
我目前正在尝试提高我的服务器的性能,我已经为此工作了几天,但到目前为止我还没有找到解决方案。
我使用的是 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 = "Whosebug",
).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 不是正确的地方(并且很可能会导致一堆附带问题)但我希望你明白了。
这有可能吗?还是我已经走到了死胡同?如果可能,我该怎么做?
只需筛选 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="Whosebug")
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, [])
我目前正在尝试提高我的服务器的性能,我已经为此工作了几天,但到目前为止我还没有找到解决方案。 我使用的是 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 = "Whosebug",
).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 不是正确的地方(并且很可能会导致一堆附带问题)但我希望你明白了。
这有可能吗?还是我已经走到了死胡同?如果可能,我该怎么做?
只需筛选 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="Whosebug")
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, [])