如何比较Django查询集中实例的字段值?

时间:2013-12-03 09:57:06

标签: python django django-queryset

我正在尝试在Django中构造一个查询集,其中一个字段的值不包含在同一个表的任何实例中。举个例子,采用这个模型:

class MyModel(models.Model):
    text  = models.CharField(max_length = 100)

我可以使用以下循环获得非重复的查询集:

from django.db.models import Q
not_contained = MyModel.objects.all()
for instance in MyModel.objects.all():
    not_contained=not_contained.exclude(Q(text__contains=instance.text) & ~Q(id=instance.id))

我的问题是,是否有更直接地这样做的方法,并避免在这里显式循环?

1 个答案:

答案 0 :(得分:1)

我认为你可以在这里使用extra()。

例如:

>>> MyModel.objects.all()
[<MyModel: unique>, <MyModel: onemore>, <MyModel: foo>, <MyModel: bar>, <MyModel: bar123>]
>>> MyModel.objects.extra(select={'cnt': 'SELECT COUNT (*) FROM myapp_mymodel B WHERE B.text LIKE "%%" || myapp_mymodel.text || "%%"'}, where=['cnt = 1'])
[<MyModel: unique>, <MyModel: onemore>, <MyModel: foo>, <MyModel: bar123>]

如您所见,第二个查询集不包含“bar”。额外的缺点是它是特定于DBMS的。示例适用于sqlite(对于mysql,您可能需要使用CONCAT等替换||)。

如果你有理解代码的麻烦,sql查询可以帮助:

>>> print MyModel.objects.extra(select={'cnt': 'SELECT COUNT (*) FROM myapp_mymodel B WHERE B.text LIKE "%%" || myapp_mymodel.text || "%%"'}, where=['cnt = 1']).query
SELECT (SELECT COUNT (*) FROM myapp_mymodel B WHERE B.text LIKE "%" || myapp_mymodel.text || "%") AS "cnt", "myapp_mymodel"."id", "myapp_mymodel"."text" FROM "myapp_mymodel" WHERE (cnt = 1)