2011-06-17 17 views
1

我有一個醜陋的循環,它在Django中作爲一個創可貼來操作,我想優化成加入。我已經把它分解成最基本的結構來幫助簡化問題。我希望以前有人遇到類似這樣的事情 - 如果不是,我會在我最終修復它時分享答案。Django查詢優化:找到基於多對一到多對象的對象列表

總結

  • 對象A有自身是非對稱的,許多一對多的關係。
  • 對象B與對象A
  • 一個多到一的關係,給定一個對象B,我需要一組其他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的通過加入得到ObjectBs的列表,所以這個痛苦無效的循環將不會運行?

回答

2

給定一個對象B,我需要一套 是孩子被相關 我們的對象B的父對象A的ObjectAs的 其他ObjectBs。

如果objb是你給出的對象B,你可以這樣做如下:

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

+0

感謝您抽出寶貴有時間回答 - 我當然需要更熟悉Django的QuerySet。 – 2011-06-17 13:22:52