django - 在 Django 中查找多对多类别树的根

标签 django many-to-many

我有一个像这样的 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 调用找到“没有 parent 的类别列表”?我试过:

# 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)

但如前所述,两者都不起作用。

最佳答案

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)

关于django - 在 Django 中查找多对多类别树的根,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/889040/

相关文章:

python - 在Linux上部署Django项目

python - ListSerializer 断言错误

python - 如何完成 django-userena 和 Social Auth 的集成

mysql - 在数据库中表示多对多关系的最佳方式是什么?

mysql - 应该如何在 Django ManyToMany 模型或 MySQL 中实现唯一集?

java - 多对多 JPA Hibernate 通过连接表映射复合键错误

mysql - 如何为具有多对多关系的 2 个 MySQL 表创建默认关系?

django 应用程序使用rest api - 在哪里放置代码

python - 使用 django cleaned data pop 在提交到 db 之前删除数据

sql - 如何使用 libreoffice base 中的表单以多对多关系添加/修改数据?