似乎 Django 开发人员意识到在 MySQL 中无法过滤这样的计算字段:
SomeModel.objects.extra(select={ 'total': 'SOME CALCULATION GOES HERE' }, where=['total < 10'])
或者
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)
问题是:有人知道如何克服这个暂时的(希望如此)限制并完成任务吗?任何可能的替代方案?