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

Posted

技术标签:

【中文标题】如何在 django 的自引用模型中优化相关记录的检索?【英文标题】:How do I optimize retrieval of related records in self referencing model in django? 【发布时间】:2011-07-18 17:51:35 【问题描述】:

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

parentcat3 > parentcat2 > parentcat1 > leafcategory

最后一个类别用leafCategory=True表示。

我已经覆盖了我的 ModelForm 以选择仅使用叶(结束)类别的记录;

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

然后,ModelForm 下拉菜单使用模型中 __unicode__ 的返回值;

getFullPathString()

这会返回“树”以查找父类别。这是慢的部分(有10000个类别)

如何优化父记录的检索?

这是我正在使用的代码:

型号

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】:

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

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

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

【讨论】:

+1 for django-mptt,虽然有时通过物化路径建模树,正如 django-treebeard 提供的那样,也非常有用 为什么不缓存路径?在这种特定情况下似乎非常简单有效 @Tommaso 谢谢。这种方式最适合我。

以上是关于如何在 django 的自引用模型中优化相关记录的检索?的主要内容,如果未能解决你的问题,请参考以下文章

管理员或视图中的自引用对称多对多 Django 模型

Django模型:如何避免在使用来自同一个表的2个外键时引用相同的记录

Django模型父链接的自定义相关名称?

Django Admin Cookbook-8如何在Django admin中优化查询

Rails 活动记录中的自引用问题

Django模型字段实际上是对相关模型中的字段的引用