2009-05-20 36 views
2

我有一個Django模型,如:發現許多到多類樹的根在Django

class Category(models.Model): 
    status=models.CharField(max_length=16) 
    machineName=models.CharField(max_length=50) 
    readableName=models.CharField(max_length=100) 
    description=models.CharField(max_length=1024) 
    parents=models.ManyToManyField('self') 

如果每個類別可能很多家長存在。有些類別沒有父母,他們是「根」類別。在普通的SQL我可以找到他們:

SELECT "readableName" 
FROM foo_category AS c 
LEFT JOIN foo_category_parents AS cp ON (c.id=cp.from_category_id) 
WHERE cp.to_category_id IS NULL; 

事實上,這個效果很好。如何通過Django-y調用找到「沒有父母的類別列表」?我試過了:

# Says "Cannot resolve keyword 'is_null' into field." 
Category.objects.filter(parents__is_null=True) 
# Says "Join on field 'id' not permitted." 
Category.objects.filter(parents__pk_null=True) 

但是如上所述,兩者都不起作用。

回答

7

Django的多對多字段通常對稱運行(請參閱此entry in the Django docs)。當你爲自己做一個ManyToMany時,這意味着將創建一個反向的ManyToMany條目,因此實際上每個具有父代的類別都將是父代的父代(如果有意義的話)。

換句話說:

a = Category.objects.create(name='a') 
b = Category.objects.create(name='b') 
b.parents.add(a) 

print b.parents.all() # produces [a] 
print a.parents.all() # produces [b], which is why your filter is failing 

爲了解決這個問題,有一個特殊的選項:

class Category(models.Model): 
    # ... as above ... 
    parents=models.ManyToManyField('self', symmetrical=False) 

現在你可以得到父類:

Category.objects.filter(parents=None) 
+0

太好了,謝謝你,「symmetrical = False」和「parents = None」正是我所需要的。當然「父母=無」的語法比我失敗的嘗試要好得多! – arantius 2009-05-20 19:13:16