Django查询优化:根据多对一到多对多查找对象列表

时间:2011-06-17 12:49:09

标签: python sql django

我有一个丑陋的循环,在Django中作为创可乐运行,我想优化成一个连接。我把它分解为最基本的结构,以帮助简化问题。我希望别人之前碰到过这样的事情 - 如果没有,我会在最后修复时分享答案。

总结

  • 对象A 与自身具有非对称,多对多的关系。
  • 对象B 与对象A具有多对一关系。
  • 鉴于 ObjectB ,我需要一组其他 ObjectBs ,它们是 ObjectAs 的子代,与我们的相关联ObjectB的 ObjectA

我确信拥有更多数据库经验的人可以说得更好(如果您对此关联有更好的描述,请发表评论)。

以下是我在Django中使用的结构的简单示例,以及正在运行的循环类型:

class ObjectA(models.Model):
    object_a_rules = models.ManyToManyField("self", symmetrical=False, through='ObjectARule')

class ObjectARule(models.Model):
    object_a_one = models.ForeignKey(ObjectA, related_name="object_a_before")
    object_a_two = models.ForeignKey(ObjectA, related_name="object_a_after")

class ObjectB(models.Model):
    object_a_association = models.ForeignKey(ObjectA)

    def that_annoying_loop_i_mentioned(self):
        object_a_rules_list = ObjectARule.objects.filter(object_a_one = self.object_a_association)
        #A list of all of the ObjectARules that have the ObjectA this ObjectB is associated with
        #as the first half of the many-to-many relationship.

        object_b_list = ObjectB.objects.all()
        #A list of all of the ObjectBs, may also be a filtered list

        for object_a_rule in object_a_rules_list:
            for object_b in object_b_list:
                if (object_a_rule.object_a_two == object_b.object_a_association):
                #if the second half of ObjectARule is the ObjectA of
                #the ObjectB in this list, then do something with that ObjectB.
                pass

Django如何通过连接获取ObjectB的列表,所以这个非常低效的循环不必运行?

1 个答案:

答案 0 :(得分:2)

  

给定一个ObjectB,我需要一组   其他作为子节点的ObjectB   与之关联的ObjectAs   使用我们的ObjectB的父ObjectA。

如果objb是你给出的ObjectB,你可以这样做:

objects = ObjectB.objects.filter(object_a_association__object_a_rules=objb.object_a_association)

或者,

objects = ObjectB.objects.filter(object_a_association__object_a_rules__objectb_set=objb)

另见Lookups that span relationships