【问题标题】:How to compare field values across instances in a Django queryset?如何在 Django 查询集中跨实例比较字段值?
【发布时间】:2013-12-03 09:57:05
【问题描述】:

我试图在 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))

我的问题是是否有办法更直接地做到这一点并避免这里的显式循环?

【问题讨论】:

    标签: python django django-queryset


    【解决方案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”。 extra 的缺点是它是特定于 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)
    

    【讨论】:

    • 感谢您的回答,由于我不知道 .extra() 选项,因此我最终使用了使用游标的原始 sql 命令。将尝试使用它,它很好,因为它像任何其他过滤一样返回查询集。
    猜你喜欢
    • 2019-06-04
    • 2019-01-11
    • 2016-08-17
    • 2020-06-13
    • 2021-01-02
    • 2013-04-10
    • 2017-12-17
    • 2011-10-18
    • 2017-12-16
    相关资源
    最近更新 更多