Django相当于SqlAlchemy`any`来过滤`WHERE EXISTS`

时间:2015-11-17 18:49:11

标签: django django-models sqlalchemy django-orm

我有两个模型,SampleRunSample可以属于多个Run。我要使用Run模型name来过滤Sample;我想找到所有使用给定Samples过滤器运行的name。在SqlAlchemy中,我写道:

Sample.query.filter(Sample.runs.any(Run.name.like('%test%'))).all()

在Django中,我从:

开始
Sample.objects.filter(run__in=Run.objects.filter(name__icontains='test'))

Sample.objects.filter(run__name__icontains='test')

但是这两个都会产生重复,所以我必须在最后添加.distinct()

当存在大量谓词时,使用distinct的Django方法性能很差(因为distinct操作必须在大量可能的行上运行),而SqlAlchemy运行正常。重复的行来自每个谓词的重复left outer join

例如:

Sample.objects.filter(Q(**{'run__name__icontains': 'alex'}) |
     Q(**{'run__name__icontains': 'baz'}) | ...)

编辑:为了让这更加复杂,我确实希望能够使用以下过滤器:

(Q(**{'run__name__icontains': 'alex'}) | Q(**{'name__icontains': 'alex'})
  & Q(**{'run__name__icontains': 'baz'}) | Q(**{'name__icontains': 'baz'}))

具有SQLAlchemy查询,如:

clause1 = Sample.runs.any(Run.name.like('%alex%')) | Sample.name.like('%test%')
clause2 = Sample.runs.any(Run.name.like('%baz%')) | Sample.name.like('%baz%')
Sample.query.filter(clause1 & clause2)

1 个答案:

答案 0 :(得分:0)

假设这是你的models.py:

from django.db import models

class Sample(models.Model):
    name = models.CharField(max_length=255)

class Run(models.Model):
    name = models.CharField(max_length=255)
    sample = models.ForeignKey(Sample)

由于我无法在不使用“distinct”或不使用“raw”的情况下弄清楚如何执行此操作(其中,如果您正在构建自己的SQL代码,并且不能依赖于ORM那么重点是:p),我建议尝试用SQLAlchemy替换Django ORM,或者将它们彼此并排使用,因为从理论上说这将起作用。对不起,我的帮助不大:(

这是一篇相当新的博客文章,可以帮助您做到这一点: http://rodic.fr/blog/sqlalchemy-django/