Аннотация Django ORM с обходом дерева - PullRequest
0 голосов
/ 27 декабря 2018

Я использую библиотеку 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'
...