如何优化 django 中自引用模型中相关记录的检索?

发布于 2024-10-24 07:35:29 字数 1745 浏览 4 评论 0原文

我正在从模型创建表单。该表单包含一个类别。类别模型是一个自引用模型。我想在表单的下拉列表中显示类别,以便它们也显示其父类别。即,

parentcat3 >父猫2>父猫1> 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)

I am creating a form from a model. This form contains a category. The category model is a self referencing model. I want to display the categories in a dropdown on the form so they show their parent categories too. ie,

parentcat3 > parentcat2 > parentcat1 > leafcategory

the last category is denoted by leafCategory=True.

I have overridden my ModelForm to select records only that are leaf (end) categories using;

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

The ModelForm dropdown then uses the return value from __unicode__ in the model which is;

getFullPathString()

This walks back up the 'tree' to find the parent categories. This is the part that is slow (there are 10,000 categories)

How can I optimize the retrieval of the parent records?

Here is the code I am using:

Model

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

Form

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

七禾 2024-10-31 07:35:29

这段代码效率极其低下。它将针对每个类别以及每个类别的祖先执行一系列新的数据库查询。

您需要研究针对在数据库中存储和检索此类分层数据进行优化的算法。 django-mptt 是我最喜欢的。

顺便说一句,在列表的开头重复插入元素也是低效的。列表针对附加进行了优化,但并未针对插入进行优化。为在两端添加而优化的数据结构是 Python 的 collections 模块中的 deque - 但更好的解决方案可能是简单地附加元素,然后调用 reverse () 在返回列表之前。

This code is incredibly inefficient. It will do a new series of database queries for every single category, and for each category's ancestor.

You need to look into the algorithms that are optimised for storing and retrieving this sort of hierarchical data in a database. django-mptt is my favourite of these.

As an aside, it is also inefficient to repeatedly insert elements at the start of a list. Lists are optimised for appending, they are not optimised for inserting. A data structure optimised for adding at both ends is the deque in Python's collections module - but a better solution would probably be to simply append the elements, then call reverse() on the list before returning it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文