2009-11-28 50 views
4

我有一個模型是這樣的:一個關於Q對象鍵和外鍵拼圖

class Thing(models.Model): 
    property1 = models.IntegerField() 
    property2 = models.IntegerField() 
    property3 = models.IntegerField() 

class Subthing(models.Model): 
    subproperty = models.IntegerField() 
    thing = modelsForeignkey(Thing) 
    main = models.BooleanField() 

我有傳遞的過濾器列表的功能,其中每個過濾器的形式爲{「類型':某事,'價值':x}。此功能需要返回的結果集取與所有的過濾器一起:

final_q = Q() 
for filter in filters: 
     q = None 
     if filter['type'] =='thing-property1': 
      q = Q(property1=filter['value']) 
     elif filter['type'] =='thing-property2': 
      q = Q(property2=filter['value']) 
     elif filter['type'] =='thing-property2': 
      q = Q(property3=filter['value']) 
     if q: 
      final_q = final_q & q 
return Thing.objects.filter(final_q).distinct() 

每個Subthing有一個布爾屬性「主」。 Every Thing有1個,只有1個主要==真的東西。

我現在需要添加過濾器,返回所有有Subthing其中main==Truesubproperty==filter['value']

我能做到這一點的Q對象,我構建的一部分的東西呢?如果不是如何呢?在我的新過濾器之前得到的查詢集可能非常大,所以我想要一個不涉及循環結果的方法。

+0

有一個錯字,應該是models.ForeignKey() – Evgeny 2009-11-28 23:45:54

回答

2

這是一個有點容易理解,如果你明確地給你Subthings一個「related_name」在他們對事物的

class Subthing(models.Model): 
    ... 
    thing = models.ForeignKey(Thing, related_name='subthings') 
    ... 

關係現在,您使用Django join syntax構建您的問與答對象:

Q(subthings__main=True) & Q(subthings__subproperty=filter['value']) 

反向關係具有默認名稱'subthing_set',但我發現如果您給它一個更好的名稱,如'subthings',則更容易遵循。

+0

Doh!出於某種原因,我正在尋找比這更復雜的解決方案!這似乎是完美的。 – 2009-11-29 10:41:14

1

使用(而不是在一開始final_q=Q()

final_q=Q(subthing_set__main=True) 
sub_vals = map(lambda v: v['value'], filters) 
if sub_vals: 
    final_q = final_q & Q(subthing_set__subproperty__in=sub_vals) 

應該得到你想要的東西,你也可以調整你的循環建立sub_vals列表和循環後應用它。

subthing_set被添加到Thing中並自動添加相關字段以訪問相關的Subthings。

您可以指定另一個相關的名稱,例如

thing=models.ForeignKey(Thing,related_name='subthings')