如果仅需要更改xlsx中True / False的显示方式-一种选择是仅使用一个related_exists
BooleanField注释,然后在创建xlsx文档时(即在序列化程序中)自定义其转换方式。数据库应存储原始/未格式化的值,然后应用程序准备将其显示给用户。
要考虑的其他事项:
- 索引以加速过滤。
- 如果过滤后有数百万条记录,则在一个表中-也许可以考虑对表进行分区。
但是让我们看一下原始查询的原始sql。就像这样:
SELECT [model_fields],EXISTS([CLIENT_SELECT]) AS related_exists,CASE
WHEN EXISTS([CLIENT_SELECT]) = true THEN 'The relation exists!'
WHEN EXISTS([CLIENT_SELECT]) = true THEN 'The relation does not exist!'
ELSE 'The relation exists!'
END AS related_column
FROM model;
现在,我们可以看到存在的CLIENT_SELECT存在的嵌套查询有3次。即使完全相同,也可以执行最少2次,最多3次。数据库可能会将其优化为快于3倍,但仍然不是1倍。
首先,EXISTS
返回True或False,我们只需要检查一下它是否为True,即可将'The relation does not exist!'
设为默认值。
related_column=Case(
When(related_exists=True,then=Value('The relation exists!')),default=Value('The relation does not exist!')
为什么related_column
再次执行相同的选择却不采用related_exists
的值?
因为我们在计算另一列时不能引用计算所得的列-这是django知道的数据库级约束,并且重复了表达式。
等等,那么我们实际上不需要related_exists
列,只需将related_column
留在CASE语句中,并保留1个存在的子查询。
Django来了-直到3.0,我们才能在过滤器中使用表达式而不先对其进行注释。
因此,我们的情况是这样的:为了在Exist
中使用When
,我们首先需要将其添加为注释,但不会用作参考,而是表达式的完整副本。
好消息!
自Django 3.0起,我们可以直接在QuerySet过滤器中使用直接输出BooleanField的表达式,而无需先注释。 Exists
是此类BooleaField表达式之一。
Model.objects.all().annotate(
related_column=Case(
When(
Exists(RelatedModel.objects.filter(foreign_key_model=OuterRef('id'))),then=Value('The relation exists!'),),default=Value('The relation doesn't exist!'),output_field=CharField(),)
)
只有一个嵌套的select和一个带注释的字段。
Django 2.1,2.2
这是commit,它确定了布尔表达式的允许量,尽管之前已为其添加了许多前提条件。其中之一是表达式对象上存在conditional
属性,并检查该属性。
因此,尽管不推荐和未测试,但对于Django 2.1、2.2来说,它似乎几乎没有什么作用(在没有conditional
检查之前,将需要更多的侵入性更改):
- 创建
Exists
表达式实例
- 猴子用
conditional = True
修补
- 将其用作
When
语句中的条件
related_model_exists = Exists(RelatedModel.objects.filter(foreign_key_model=OuterRef('id')))
setattr(related_model_exists,'conditional',True)
Model.objects.all().annotate(
related_column=Case(
When(
relate_model_exists,)
)
相关检查
relatedmodel_set__isnull=True
检查不出于以下几个原因:
- 它执行
LEFT OUTER JOIN
-比EXISTS
效率低
- 它执行
LEFT OUTER JOIN
-它联接表,这使其仅适用于filter()条件(不适用于注释-何时),并且仅适用于OneToOne或OneToMany(一个在relatedmodel一侧)关系
,
您可以将查询大大简化为:
from django.db.models import Count
Model.objects.all().annotate(
related_column=Case(
When(relatedmodel_set__isnull=True,then=Value("The relation doesn't exist!")),default=Value("The relation exists!"),output_field=CharField()
)
)
relatedmodel_set
是外键上的related_name
。
本文链接:https://www.f2er.com/3018135.html