Аннотация Django ORM с обходом дерева
Я использую библиотеку django-mptt для создания категорий для моего проекта. Модель довольно проста:
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel):
name = models.CharField('Name', max_length=100, unique=True)
color = models.CharField(
'Color',
max_length=100,
blank=True,
null=True
)
parent = TreeForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='children'
)
class MPTTMeta:
order_insertion_by = ['name']
Цвет категории является необязательным и должен наследоваться от родителя, если он не определен. Так что просто для иллюстрации:
Main Category 1 (red) -> Subcategory 1
-> Subcategory 2 (blue)
-> Subcategory 3 (yellow) -> Subcategory 4
Подкатегория 4 не имеет определенного цвета и наследует цвет подкатегории 3 (желтый). Подкатегория 1 наследует цвет от основной категории 1 (синий) и т. Д.
На мой взгляд, у меня есть корневая категория, а затем построить дерево, используя get_descendants(include_self=True)
,
Как я могу аннотировать цвет для каждой категории <TreeQuerySet>
?
Для одной модели у меня есть следующий метод:
@property
def inherited_color(self):
if self.color:
return self.color
return (self
.get_ancestors(ascending=True, include_self=True)
.filter(color__isnull=False)
.values_list('color', flat=True)
.first())
Но когда этот метод вызывается для списка категорий, это приводит к большому количеству запросов к базе данных!
Это пример из оболочки django:
>>> category
<Category: 3>
>>> category.color is None
True
>>> category.get_family().values_list('name', 'color')
<TreeQuerySet [('1', '#51DCFF'), ('2', None), ('3', None)]>
>>> category.inherited_color
'#51DCFF'