如何优化 fetch 和相关对象加载?
How optimize fetch and related objects loading?
我是 django 的初学者,在寻找解决方案几个小时后,我终于寻求帮助。我想用我的模型找到 retrieve/fetch 数据的最佳方式(性能)。我尝试了几件事,并阅读了有关 select_related、prefetch_related.
的文档
具体问题是:
我有一个 specific_id 的列表,是从 Web 服务中检索到的,我需要加载相应的对象(按照列表给出的正确顺序)和一些相关对象。
我的模型:
我有一个产品与 0-N 个存储库相关(来自存储库的 FK)。
该产品也有 0-N 来源(一对 0-N 传感器和 0-N 平台),通过 sourcecontribtoproduct
class Product(models.Model):
specific_id = models.CharField(max_length=100, unique=True, blank=False, null=False)
shortname = models.CharField(max_length=100, unique=False, blank=True, null=False)
class Repository(models.Model):
product = models.ForeignKey(Product, blank=True, null=True)
name = models.CharField(max_length=200, unique=True, blank=False, null=False)
url = models.CharField(max_length=2048, blank=True, null=True)
class SourceContribToProduct(models.Model):
source = models.ForeignKey(Source)
product = models.ForeignKey(Product)
class Source(models.Model):
products = models.ManyToManyField(Product, through='SourceContribToProduct')
shortname = models.CharField(max_length=100, unique=True, blank=False, null=False)
platform = models.ForeignKey(Platform, blank=True, null=True)
sensor = models.ForeignKey(Sensor, blank=True, null=True)
class Sensor(models.Model):
shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
type = models.TextField(blank=True, null=True)
class Platform(models.Model):
shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
description = models.TextField(blank=True, null=True)
因此,正如我所说,我需要检索包含所有存储库、源和平台的产品列表。这是我在 views.py
中所做的
# Retrive list of objects
products = Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set')
for p in products:
p.repositories = p.repository_set.all()
p.sources = Source.objects.filter(sourcecontribtoproduct__product_id=p.id).select_related('sensor_set', 'platform_set')
for s in p.sources:
s.sensor
s.platform
# Sort the list
products = list(products)
products.sort(key=lambda t: ids.index(t.specific_id))
你觉得这段代码怎么样?我怎么能优化这个治疗,因为我觉得这太长了。我只有 194 个产品(最多 5 个存储库相关,不超过 3 个来源),我的浏览器需要大约 5 秒才能显示结果。有没有一种方法可以简单地默认加载嵌套/相关对象?
感谢阅读,
嗯,我找到了解决我的问题的方法,我不需要迭代视图中的对象来加载它们。只需要在模板中创建一个查询集和访问。像这样:
在view.py
products=Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set').select_related('repository_set', 'source_set')
然后在我的模板中迭代:
{% for src in product.source_set.all %}
{{src.platform.shortname}} / {{src.sensor.shortname}}<br/>
{% endfor %}
{% for repo in product.repository_set.all %}
{{repo.url}}%}
{% endfor %}
就这些了...
我是 django 的初学者,在寻找解决方案几个小时后,我终于寻求帮助。我想用我的模型找到 retrieve/fetch 数据的最佳方式(性能)。我尝试了几件事,并阅读了有关 select_related、prefetch_related.
的文档具体问题是:
我有一个 specific_id 的列表,是从 Web 服务中检索到的,我需要加载相应的对象(按照列表给出的正确顺序)和一些相关对象。
我的模型:
我有一个产品与 0-N 个存储库相关(来自存储库的 FK)。 该产品也有 0-N 来源(一对 0-N 传感器和 0-N 平台),通过 sourcecontribtoproduct
class Product(models.Model):
specific_id = models.CharField(max_length=100, unique=True, blank=False, null=False)
shortname = models.CharField(max_length=100, unique=False, blank=True, null=False)
class Repository(models.Model):
product = models.ForeignKey(Product, blank=True, null=True)
name = models.CharField(max_length=200, unique=True, blank=False, null=False)
url = models.CharField(max_length=2048, blank=True, null=True)
class SourceContribToProduct(models.Model):
source = models.ForeignKey(Source)
product = models.ForeignKey(Product)
class Source(models.Model):
products = models.ManyToManyField(Product, through='SourceContribToProduct')
shortname = models.CharField(max_length=100, unique=True, blank=False, null=False)
platform = models.ForeignKey(Platform, blank=True, null=True)
sensor = models.ForeignKey(Sensor, blank=True, null=True)
class Sensor(models.Model):
shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
type = models.TextField(blank=True, null=True)
class Platform(models.Model):
shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
description = models.TextField(blank=True, null=True)
因此,正如我所说,我需要检索包含所有存储库、源和平台的产品列表。这是我在 views.py
中所做的# Retrive list of objects
products = Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set')
for p in products:
p.repositories = p.repository_set.all()
p.sources = Source.objects.filter(sourcecontribtoproduct__product_id=p.id).select_related('sensor_set', 'platform_set')
for s in p.sources:
s.sensor
s.platform
# Sort the list
products = list(products)
products.sort(key=lambda t: ids.index(t.specific_id))
你觉得这段代码怎么样?我怎么能优化这个治疗,因为我觉得这太长了。我只有 194 个产品(最多 5 个存储库相关,不超过 3 个来源),我的浏览器需要大约 5 秒才能显示结果。有没有一种方法可以简单地默认加载嵌套/相关对象?
感谢阅读,
嗯,我找到了解决我的问题的方法,我不需要迭代视图中的对象来加载它们。只需要在模板中创建一个查询集和访问。像这样:
在view.py
products=Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set').select_related('repository_set', 'source_set')
然后在我的模板中迭代:
{% for src in product.source_set.all %}
{{src.platform.shortname}} / {{src.sensor.shortname}}<br/>
{% endfor %}
{% for repo in product.repository_set.all %}
{{repo.url}}%}
{% endfor %}
就这些了...