Django ORM:过滤计算字段MySQL状态/变通方法

时间:2012-12-22 21:55:54

标签: django django-orm

Django开发人员似乎意识到在MySQL中没有办法过滤这样的计算字段:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['total < 10'])

OR

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }).filter(total__lt=10)

这在https://code.djangoproject.com/ticket/8784中有所描述,但不幸的是,看起来需要一年的时间来实现目前的速度。我理解开发团队的关注,理想情况下他们想要摆脱.extra(),因为通过在该语句中编写纯SQL代码变得非DB无关。我认为在许多项目中处理计算字段是相当常见的任务,我目前面临的问题是我无法解决:我认为大多数社区经常使用这种肮脏的解决方法:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['1 HAVING total < 10'])

实际上它可以工作,但直到您需要在上述语句的结果上添加过滤器的那一刻:

SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['1 HAVING total < 10']).filter(id__gt=300)

这不再起作用,因为它转换为错误的SQL语句:

SELECT id, ..., (SOME CALCULATION) AS total
FROM some_table
WHERE (1 AND HAVING total < 10 AND id > 300)

我想要实现的是在自定义模型管理器中有某种​​限制,这将允许我编写这样的代码:

class SomeModelManager(models.Manager):
  def apply_total_restriction(self, restriction_num):
    return self.extra(select={ 'total': 'CALCULATION GOES HERE' }).filter(total__lt=restriction_num)

...

SomeModel.objects.apply_total_restriction(restriction_num).filter(created_by_id__exact=1)

问题是:有人知道如何克服这种暂时的(希望)限制并完成任务吗?任何可能的替代方案?

1 个答案:

答案 0 :(得分:0)

我找到了解决方案:我认为在WHERE子句中再次计算该字段会太慢,但是当我尝试它时它变得非常快并且不需要HAVING。以下是我的意思:

SELECT (a + b / 2) as 'c', a, b FROM table WHERE (a + b / 2) >= 20 AND a != b

基本上就是这样 - 如果你认为你需要HAVING,试着用HAVING测量时间并再次计算计算字段并在WHERE中过滤它然后得出结论来比较时间。