我研究了可用的django聚合函数,并注意到那里缺少对数。所以,我的问题是:如何在对Queryset的注释中使用对数?我无法在Queryset评估后取对数,因为我需要不完全用对数进行注释,而需要使用包含对数的表达式进行注释,例如对于某些模型User
和Task
,我需要注释{{1} }和User
/ F('task__cost')
。
UPD:如果不使用特定于数据库的函数(对于Postgres)也可以做到这一点,那是很棒的,但是这种解决方案也是可能的。
答案 0 :(得分:1)
Django具有这些功能,这些功能已添加到pull request 9622 [GitHub]中。在开发分支中,这些已经存在于django.db.models.functions.math
模块下。但不在django-2.1版本中。 Django开发人员文档中的一个页面为lists the source code。
事实证明此功能在most popular database systems the same [Django ticket]上。您可以添加source code [GitHub]:
from django.db.models import ( DecimalField, FloatField, Func, IntegerField, Transform, ) from django.db.models.functions import Cast # ... class DecimalInputMixin: def as_postgresql(self, compiler, connection, **extra_context): # Cast FloatField to DecimalField as PostgreSQL doesn't support the # following function signatures: # - LOG(double, double) # - MOD(double, double) output_field = DecimalField(decimal_places=sys.float_info.dig, max_digits=1000) clone = self.copy() clone.set_source_expressions([ Cast(expression, output_field) if isinstance(expression.output_field, FloatField) else expression for expression in self.get_source_expressions() ]) return clone.as_sql(compiler, connection, **extra_context) class OutputFieldMixin: def _resolve_output_field(self): has_decimals = any(isinstance(s.output_field, DecimalField) for s in self.get_source_expressions()) return DecimalField() if has_decimals else FloatField() # ... class Log(DecimalInputMixin, OutputFieldMixin, Func): function = 'LOG' arity = 2 def as_sqlite(self, compiler, connection, **extra_context): if not getattr(connection.ops, 'spatialite', False): return self.as_sql(compiler, connection) # This function is usually Log(b, x) returning the logarithm of x to # the base b, but on SpatiaLite it's Log(x, b). clone = self.copy() clone.set_source_expressions(self.get_source_expressions()[::-1]) return clone.as_sql(compiler, connection, **extra_context)
,然后导入定义的Log
函数,并按如下方式使用它:
User.objects.annotate(cost_solve_ratio=F('task__cost') / Log('task__solved_count'))