Django等价于SqlAlchemy“any”以筛选“WHERE EXISTS”



我有两个型号,SampleRun。一个Sample可以属于多个Runs。Run模型有name,我想用它来过滤Samples;我想找到所有使用给定name过滤器运行的Samples。在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操作必须在大量可能的行上运行),使用distinct的Django方法具有糟糕的性能,而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)

假设这是您的模型.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/

最新更新