2009-05-20 38 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