2012-11-12 30 views
5

我有以下型號繼承結構在Django:Django的過濾器基類的子類名稱

class Parent(models.Model): 
    # stuff 

class A(Parent): 
    # stuff 

class B(Parent): 
    # stuff 

class C(Parent): 
    # stuff 

and the list goes on. 

我使用的Django模型utils的的InheritanceManager過濾狀物體:

Parent.objects.filter(foo=bar).select_subclasses() 

當我想要過濾所有的子類時,這很有效。我想要做的是過濾A和B對象,但不過濾C對象。我想用一個單獨的查詢要做到這一點像

Parent.objects.filter(foo=bar, __class__.__name__=A, __class__.__name__=B).select_subclasses() 

是否有可能做這樣的過濾操作,如果可能的話怎麼樣?

+0

爲什麼不只是做'A.objects.filter(foo = bar)'等? –

+0

我想用單個查詢來過濾所有對象,而不是多個查詢 –

回答

0

它通常不被認爲是最好的設置可繼承的,因爲然後每個SQL查詢將不得不做一個連接。這可能會讓你的表現慢得多。爲了提高性能,您可以使用abstract meta值:

class Parent(models.Model): 
    # stuff 
    class Meta: 
     abstract = True 

這樣每個表都是獨立的,因此性能會更快。

如果這不適用於您,我認爲它不可能在單個查詢中這樣做,因爲表/模型中的字段在它們所在的表中沒有包含任何信息。在這種情況下,你很可能不得不以某種方式繼承InheritanceManager,但我不知道該怎麼做。如果你這樣做,那麼使用content_types可能會有一些幫助。

如果這是太多的工作,那麼你總是可以做一個簡單的黑客(更多的猴子修補......)。我知道它不漂亮,但它的工作:

class Parent(models.Model): 
    # stuff 
    table = models.CharField(max_length=8, default='parent') 

class A(Parent): 
    # stuff 
    table = models.CharField(max_length=8, default='a') 

class B(Parent): 
    # stuff 
    table = models.CharField(max_length=8, default='b') 


# and then something like 
# please note that I've never used django-model-utils 
# so don't know the correct syntax 
Parent.objects.filter(foo=bar, table__in=['parent', 'a']).select_subclasses() 
+0

好的謝謝。我沒有使用抽象基類,因爲我希望能夠使用單個查詢來過濾基類對象,而不是對每個子類使用單獨的查詢。我只想在某些地方過濾基類的子集,而在另一個地方過濾另一個子集。如果我找到滿意的解決方案,我會在這裏發帖 –

0

這對我的工作的另一個哈克的解決方案,而無需添加更多的信息到數據庫:

letters = Parent.objects.filter(foo=bar) 
for letter in letters: 
    if type(letter) == C: 
     letters.exclude(id=c.id) 

,或者,如果你的信息添加車型無添加字段:

class Parent(models.Model): 
    # stuff 

class A(Parent): 
    code = 'A' 
    # stuff 

class B(Parent): 
    code = 'B' 
    # stuff 

class C(Parent): 
    code = 'C' 
    # stuff 

然後......

letters = Parent.objects.filter(foo=bar) 
for letter in letters: 
    if letter.child().code == 'C': 
     letters.exclude(id=c.id) 

爲我的目的工作,雖然仍然是黑客...