我有两个型号,Sample
和Run
。一个Sample
可以属于多个Run
s。Run
模型有name
,我想用它来过滤Sample
s;我想找到所有使用给定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/