2015-03-01 2 views
0

Я пишу приложение Django, которое запрашивает базу данных Bugzilla для отчетности. Я пытаюсь создать запрос, который может получить все ошибки, которые имеют определенные флаги.Django; как найти все ошибки, которые имеют определенные флаги

Модель, представляющая таблицу флагов.

class Bugzilla_flags(models.Model): 
    class Meta: 
     db_table = 'flags' 

    type_id = models.IntegerField() 
    status = models.CharField(max_length=50) 
    bug_id = models.IntegerField() 
    creation_date = models.DateTimeField() 
    modification_date = models.DateTimeField() 
    setter_id = models.IntegerField() 
    requestee_id = models.IntegerField() 

    def __unicode__(self): 
     return str(self.bug_id) 

У меня есть словарь, который представляет собой флагов, которые я хочу найти (type_id: status).

flags = {'36':'?','12':'+'} 

Я попытался с помощью функции уменьшения, но я не думаю, что это будет работать, потому что проверяет, что все флаги должны присутствовать в той же строке. Если я выполнить запрос со словарем с помощью всего одного к, v пара, она работает нормально, но не более чем 1.

query = reduce(operator.and_, (Q(type_id=flag,status=val) for (flag,val) in flags.items())) 

Я тогда взять результаты этого запроса, а также использовать его в качестве поиск фактической базы данных ошибок.

inner = Bugzilla_flags.objects.using('bugzilla').filter(query) 
bugs = Bugzilla_bugs.objects.using('bugzilla').filter(bug_id__in=inner) 

Для некоторых истории, я в настоящее время, используя ряд шагов, чтобы сгенерировать SQL, которые я отправляю в качестве исходного запроса, но я стараюсь, чтобы увидеть, если я могу сделать это в Django. В результате SQL как это:

select b.bug_id, b.priority, b.bug_severity, b.bug_status, b.resolution, b.cf_verified_in, b.assigned_to, b.qa_contact, b.short_desc, b.cf_customercase, 
    MAX(CASE WHEN f.type_id = 31 THEN f.status ELSE NULL END) as Unlocksbranch1, 
    MAX(CASE WHEN f.type_id = 31 THEN f.status ELSE NULL END) as Unlocksbranch2, 
    MAX(CASE WHEN f.type_id = 33 THEN f.status ELSE NULL END) as Unlocksbranch3, 
    MAX(CASE WHEN f.type_id = 34 THEN f.status ELSE NULL END) as Unlocksbranch4, 
    MAX(CA5E WHEN f.type_id = 36 THEN f.status ELSE NULL END) as Unlocksbranch5, 
    MAX(CASE WHEN f.type_id = 41 THEN f.status ELSE NULL END) as Unlocksbranch6, 
    MAX(CASE WHEN f.type_id = 12 THEN f.status ELSE NULL END) as CodeReviewed 
    from bugs b 
    inner join flags f on f.bug_id = b.bug_id 
    where (b.bug_status = 'RESOLVED' or b.bug_status = 'VERIFIED' or b.bug_status = 'CLOSED') 
    and b.resolution = 'FIXED' 
    group by b.bug_id 
    having CodeReviewed = '+' and Unlocksbranch1 = '?' and Unlocksbranch2 = '+' 

В результате это дает мне один QuerySet, который имеет все флаги я забочусь о том, как колонны, которые я могу после этого сделать свой анализ на. Последний раздел «having» - это то, на что я действительно запрашиваю, и это то, что я пытаюсь получить с вышеуказанными запросами Django.

EDIT

В основном то, что мне нужно сделать, как это:

flags1 = {'36':'?'} 
flags2 = {'12':'+'} 

query1 = reduce(operator.and_, (Q(type_id=flag,status=val) for (flag,val) in flags1.items())) 
query2 = reduce(operator.and_, (Q(type_id=flag,status=val) for (flag,val) in flags2.items())) 

inner1 = Bugzilla_flags.objects.using('bugzilla').filter(query1) 
inner2 = Bugzilla_flags.objects.using('bugzilla').filter(query2) 

inner1_bugs = [row.bug_id for row in inner1] # list of just the bug_ids 
inner2_bugs = [row.bug_id for row in inner2] # list of just the bug_ids 

intersect = set(inner1_bugs) & set(inner2_bugs) 

Интерсекта представляет собой набор, который имеет все bug_ids, что я могу затем использовать в запросе Bugzilla_bugs, чтобы получить фактические данные об ошибках.

Как я могу сделать 3 операции (запрос, внутренние, inner_bugs), а затем пересекаться с использованием словаря входной переменной длины, такие как:

flags = {'36':'?','12':'+','15','?',etc} 

ответ

0

Ваш inner запрос выглядит прямо ко мне. Чтобы найти ошибки, в которых есть все эти флаги, а не только один, вы можете снова использовать reduce в and вместе с пучком flag=Q объектов или же итерации и создания нескольких предложений фильтра.

inner = Bugzilla_flags.objects.using('bugzilla').filter(query) 
flag_filter = reduce(operator.and_, (Q(flag=flag) for flag in inner)) 
bugs = Bugzilla_bugs.objects.using('bugzilla').filter(flag_filter) 

Или:

inner = Bugzilla_flags.objects.using('bugzilla').filter(query) 
bugs = Bugzilla_bugs.objects.using('bugzilla').all() 
for flag in inner: 
    bugs = bugs.filter(flag=flag) 

Или, по этому вопросу, воспользоваться тем, что многократная Q объекты and объединено:

inner = Bugzilla_flags.objects.using('bugzilla').filter(query) 
flag_filters = [Q(flag=flag) for flag in inner] 
bugs = Bugzilla_bugs.objects.using('bugzilla').filter(*flag_filters) 
+0

Ни одна из этих работ. Я всегда получаю нулевые строки, когда я делаю запрос Bugzilla_bugs с использованием фильтра. Я выяснил, как получить пересечение различных фильтров, но мне нужен чистый способ сделать это. Я редактировал вопрос. – zoidberg

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