2013-12-03 2 views
3

Я пытаюсь построить набор запросов в Django, где значения одного поля не содержатся ни в одном экземпляре той же таблицы. В качестве примера возьмем эту модель:Как сравнить значения полей между экземплярами в наборе запросов Django?

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

я могу получить не-дубликат QuerySet используя следующий цикл:

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

Я думаю, что вы можете использовать некоторые дополнительные() здесь.

Например:

>>> 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>] 

Как вы видите, второй QuerySet не содержит 'бар'. Недостаток с дополнительным - это специфичный для СУБД. Пример для 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) 
+0

Спасибо за ваш ответ, я закончил с использованием необработанной команды SQL с помощью курсора, так как я не был осведомлен о '.extra () '. Постараюсь использовать это, его приятно, поскольку он возвращает набор запросов, как и любую другую фильтрацию. – yellowcap

Смежные вопросы