递归查询集与 Django
Recursive QuerySet with django
我有这个模型引用自身以允许构建树:
class PartCategory(models.Model):
parent = models.ForeignKey('PartCategory', on_delete=models.DO_NOTHING, null=True, default=None, blank=True)
name = models.TextField()
我现在有一个 SQL 查询来获取一个元素及其所有子元素 select(在本例中为 id=64 的元素):
WITH RECURSIVE
under_partcategory(id,name, parent_id,level) AS (
select api_partcategory.id,api_partcategory.name,api_partcategory.parent_id,0 from api_partcategory where api_partcategory.id=64
UNION ALL
SELECT api_partcategory.id,api_partcategory.name,api_partcategory.parent_id, under_partcategory.level+1
FROM api_partcategory JOIN under_partcategory ON api_partcategory.parent_id=under_partcategory.id
ORDER BY 2
)
SELECT * FROM under_partcategory;
我正在寻找一种在 QuerySet 中表达此查询的方法,以允许从我的模型中添加过滤选项和字段构造,但我不太清楚这是否可行。
我能否构建一个复合查询集,该查询集由从我的模型构建的某种原始查询组成,同时允许使用 filter
和 order_by
功能?
编辑:
更具体地说,我想要一个 QuerySet 我可以使用这个 whay:
PartCategory.recursive.filter(64)
在内部,它将通过用 PartCategory 模型中的元素替换所有包含的部分来构建请求:
WITH RECURSIVE
under_{model name}({model fields},level) AS (
select {model fields},0 from {model name} {where {model name}.id=64 #extracted from filter}
UNION ALL
SELECT {model fields}, under_{model_name}.level+1
FROM {model name} JOIN under_{model_name} ON {model_name}.parent_id=under_{model_name}.id
ORDER BY 2
)
SELECT * FROM under_{model_name};
我正在与自定义管理器一起尝试构建它,但现在我不知道如何从我的模型构建 {model fields}
以及如何 return 一个符合 filter
.
编辑 2:
正如 colwin 所说,我用 django-mptt
做到了,但与我一开始想的不完全一样。
我的模型 django-mptt
变为:
from mptt.models import MPTTModel, TreeForeignKey
class PartCategory(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
name = models.TextField()
class MPTTMeta:
order_insertion_by = ['name']
为了提取我的项目 64 及其所有子项,我现在这样做:
categories = PartCategory.objects.get(id=64).get_descendants(include_self=True)
这很简单!
这不适合你吗?
parts = PartCategory.objects.raw('''
WITH RECURSIVE
under_partcategory(id,name, parent_id,level) AS (
select api_partcategory.id,api_partcategory.name,api_partcategory.parent_id,0 from api_partcategory where api_partcategory.id=64
UNION ALL
SELECT api_partcategory.id,api_partcategory.name,api_partcategory.parent_id, under_partcategory.level+1
FROM api_partcategory JOIN under_partcategory ON api_partcategory.parent_id=under_partcategory.id
ORDER BY 2
)
SELECT * FROM under_partcategory;
''')
我有这个模型引用自身以允许构建树:
class PartCategory(models.Model):
parent = models.ForeignKey('PartCategory', on_delete=models.DO_NOTHING, null=True, default=None, blank=True)
name = models.TextField()
我现在有一个 SQL 查询来获取一个元素及其所有子元素 select(在本例中为 id=64 的元素):
WITH RECURSIVE
under_partcategory(id,name, parent_id,level) AS (
select api_partcategory.id,api_partcategory.name,api_partcategory.parent_id,0 from api_partcategory where api_partcategory.id=64
UNION ALL
SELECT api_partcategory.id,api_partcategory.name,api_partcategory.parent_id, under_partcategory.level+1
FROM api_partcategory JOIN under_partcategory ON api_partcategory.parent_id=under_partcategory.id
ORDER BY 2
)
SELECT * FROM under_partcategory;
我正在寻找一种在 QuerySet 中表达此查询的方法,以允许从我的模型中添加过滤选项和字段构造,但我不太清楚这是否可行。
我能否构建一个复合查询集,该查询集由从我的模型构建的某种原始查询组成,同时允许使用 filter
和 order_by
功能?
编辑:
更具体地说,我想要一个 QuerySet 我可以使用这个 whay:
PartCategory.recursive.filter(64)
在内部,它将通过用 PartCategory 模型中的元素替换所有包含的部分来构建请求:
WITH RECURSIVE
under_{model name}({model fields},level) AS (
select {model fields},0 from {model name} {where {model name}.id=64 #extracted from filter}
UNION ALL
SELECT {model fields}, under_{model_name}.level+1
FROM {model name} JOIN under_{model_name} ON {model_name}.parent_id=under_{model_name}.id
ORDER BY 2
)
SELECT * FROM under_{model_name};
我正在与自定义管理器一起尝试构建它,但现在我不知道如何从我的模型构建 {model fields}
以及如何 return 一个符合 filter
.
编辑 2:
正如 colwin 所说,我用 django-mptt
做到了,但与我一开始想的不完全一样。
我的模型 django-mptt
变为:
from mptt.models import MPTTModel, TreeForeignKey
class PartCategory(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
name = models.TextField()
class MPTTMeta:
order_insertion_by = ['name']
为了提取我的项目 64 及其所有子项,我现在这样做:
categories = PartCategory.objects.get(id=64).get_descendants(include_self=True)
这很简单!
这不适合你吗?
parts = PartCategory.objects.raw('''
WITH RECURSIVE
under_partcategory(id,name, parent_id,level) AS (
select api_partcategory.id,api_partcategory.name,api_partcategory.parent_id,0 from api_partcategory where api_partcategory.id=64
UNION ALL
SELECT api_partcategory.id,api_partcategory.name,api_partcategory.parent_id, under_partcategory.level+1
FROM api_partcategory JOIN under_partcategory ON api_partcategory.parent_id=under_partcategory.id
ORDER BY 2
)
SELECT * FROM under_partcategory;
''')