Django:过滤自引用外键属性

Django: filter on a self-reference foreign key attribute

在我的 Django 2.2 应用程序中,我有一个这样的模型:

class Folder(models.Model):
    name = models.CharField(max_length=100)
    parent_folder = models.ForeignKey("Folder", null=True, on_delete=models.SET_NULL)

基本上,一个文件夹可以有一个父文件夹,这个文件夹的父文件夹本身也可以有一个父文件夹,依此类推。

所以我想做的是,根据 name 属性对文件夹进行排序,并从顶级文件夹开始(因此,没有 parent_folder 的文件夹),然后依次递减文件夹层次结构。

为了说明,给定 table 中的以下对象:

+----+---------+---------------+
| id |  name   | parent_folder |
+----+---------+---------------+
|  1 | fuel    | <None>        |
|  2 | blabla  | 1             |
|  3 | volcano | 2             |
|  4 | awful   | 2             |
|  5 | apple   | 1             |
|  6 | amazing | <None>        |
|  7 | wow     | 6             |
+----+---------+---------------+

我排除的有序输出是:

+----+---------+---------------+
| id |  name   | parent_folder |
+----+---------+---------------+
|  6 | amazing | <None>        |
|  7 | wow     | 6             |
|  1 | fuel    | <None>        |
|  5 | apple   | 1             |
|  2 | blabla  | 1             |
|  4 | awful   | 2             |
|  3 | volcano | 2             |
+----+---------+---------------+

使用Django MPTT即可轻松实现。

您需要的,由 .get_family() 返回(参见 docs)。

我建议为此使用 django-mptt,可以通过 pip3 install django-mptt 安装。

mptt添加到INSTALLED_APPS,然后修改您的模型:

from mptt.models import MPTTModel, TreeForeignKey

class Folder(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)

现在您只需调用 Folder.get_family(),您的查询集将默认按 "tree order" 排序。