Django的;如何找到所有设置了某些标志的bug

时间:2015-03-01 16:00:14

标签: python django

我正在编写一个Django应用程序,用于查询Bugzilla数据库以进行报告。我正在尝试构建一个查询,可以获取所有设置了特定标志的错误。

表示标志表的模型。

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':'+'}

我尝试使用reduce函数,但我认为它不会起作用,因为我正在检查所有标志是否存在于同一行中。如果我使用只有一个k,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 = '+' 

这样的结果给了我一个查询集,它包含我关心的所有标志作为列,然后我可以对其进行分析。最后一个“拥有”部分是我实际查询的内容,也是我想用上面的Django查询得到的内容。

修改

基本上我需要做的就是这样:

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个操作(query,inner,inner_bugs)然后交叉,例如:

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

1 个答案:

答案 0 :(得分:0)

您的inner查询对我来说是正确的。要查找包含所有这些标记的错误,而不仅仅是任何标记,您可以再次使用reduceand一起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)