Как оптимизировать поиск связанных записей в модели самообращения в django? - PullRequest
1 голос
/ 19 марта 2011

Я создаю форму из модели. Эта форма содержит категорию. Модель категории - это модель, ссылающаяся на себя. Я хочу отобразить категории в раскрывающемся списке формы, чтобы они также отображали свои родительские категории. т.е.

parentcat3 > parentcat2 > parentcat1 > leafcategory

последняя категория обозначена leafCategory=True.

Я переопределил свою ModelForm для выбора записей, которые используют только конечные категории;

self.fields['primaryCategory'].queryset = Category.objects.exclude(leafCategory=False)

Затем раскрывающийся список ModelForm использует возвращаемое значение из __unicode__ в модели;

getFullPathString()

Это вернется к «дереву», чтобы найти родительские категории. Это медленная часть (есть 10 000 категорий)

Как я могу оптимизировать поиск родительских записей?

Вот код, который я использую:

Модель

class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey("self",related_name='related_category',null=True)
    leafCategory=models.BooleanField(default=False)

    def __unicode__(self):
        return u"%s" % self.getFullPathString()

    def getParentArray(self):
        """Create an array of parent objects from the current category """
        itemArray=[]

        itemArray.insert(0,self)
        parentCat=self.parent

        while parentCat:
            itemArray.insert(0,parentCat)
            parentCat=parentCat.parent
        return itemArray

    def getFullPathString(self):
        """Get the parent category names, cat 1 > cat 2 etc"""
        returnText=""
        for item in self.getParentArray():
            returnText += item.name
            if not item.isLeaf():
                returnText += " > "
        return returnText

Форма

class InventoryForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(InventoryForm, self).__init__(*args, **kwargs)
        self.fields['primaryCategory'].queryset = Category.objects.exclude(leafCategory=False)

1 Ответ

2 голосов
/ 19 марта 2011

Этот код невероятно неэффективен. Он выполнит новую серию запросов к базе данных для каждой отдельной категории и для предка каждой категории.

Вам необходимо изучить алгоритмы, оптимизированные для хранения и извлечения такого рода иерархических данных в базе данных. django-mptt мой любимый из них.

Кроме того, также неэффективно многократно вставлять элементы в начале списка. Списки оптимизированы для добавления, они не оптимизированы для вставки. Структура данных, оптимизированная для добавления на обоих концах, - это модуль deque в Python collections, но лучшим решением, вероятно, было бы просто добавить элементы, а затем вызвать reverse() в списке перед его возвратом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...