Django formset,查询每个表单的关系字段

2024-10-03 17:20:05 发布

您现在位置:Python中文网/ 问答频道 /正文

在模型.py在

class Material(BaseModelClass):
    material = models.CharField(max_length=25, verbose_name='Material')
    def __str__(self):
        return self.material

class PurOrder(BaseModelClass):
    order_number = models.CharField(max_length=25)

class PurOrderItem(BaseModelClass):
    order = models.ForeignKey(PurOrder, on_delete=models.CASCADE)
    material = models.ForeignKey(Material, on_delete=models.PROTECT)

我创建了一个PurOrder表单和PurOrderItem表单集

^{pr2}$

初始化如下。在

form = PurOrderForm(instance=order_instance)
queryset = order_instance.purorderitem_set.all().select_related('material',)
formset = PurOrderFormset(instance=order_instance, queryset=queryset)

如果所选purorder有20个PurOrderItem,则此设置将花费我22个查询。在

  • 1对于PurOrder实例
  • PurOrderItem实例为1
  • 采购项目的选定材料为20

想想看,如果有1000个PurOrderItem

与所提供的select_相关,它将material添加到purderitemselect,但是当它显示它时,我想它会再次查询。在

我使用django autocomplete light,这样可以避免查询所有的材质实例,但是它会继续查询所选的材质,即使我选择了与_相关的材质,也可以显示它。在

理想情况下,我会选择带有预取purderItem和相关材料的purder实例,这意味着3个查询。当轮到他们时,将使用预取的purorderitem和material。在

请给我一个避免选择查询的方法。在

注意:我尽量避免在这里缓存。在

更新

在我提出这个问题很久之后,我尝试提供解决方案。 问题是,formset的表单彼此不知道。因此,只要queryset所选的“与”或“预取”相关的查找未传递到表单集表单。在


Tags: 实例instance表单modelsordermaxclassqueryset
2条回答

你很好。此代码将只花费您3个查询。 正如您在select_related()文档中看到的:

Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries.

这意味着您的代码将预处理mysql join,并将生成一个包含所有数据的数据集。因此,我可以看出你的代码很好。在

我建议您使用类似django-silk之类的分析来查看生成了多少查询。在

脚注:

正如您在prefetch_related()文档中看到的,prefetch_related()和{}之间的区别在于它们预处理连接的方式:

This (prefetch_related) has a similar purpose to select_related, in that both are designed to stop the deluge of database queries that is caused by accessing related objects, but the strategy is quite different.

...

select_related works by creating an SQL join and including the fields of the related object in the SELECT statement. For this reason, select_related gets the related objects in the same database query.

...

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python.

所以只要您需要one-to-one关系,select_related是查询关系的最有效方法。在

我最近意识到类似情况下的问题并不是表单集本身,而是{{表单集.错误}}在模板中,因为每个表单集为此生成一个查询。在

相关问题 更多 >