Django form queryset=model.objects.all() 加载缓慢

Posted

技术标签:

【中文标题】Django form queryset=model.objects.all() 加载缓慢【英文标题】:Django form queryset=model.objects.all() loads slowly 【发布时间】:2017-01-12 16:34:46 【问题描述】:

我有一个简单的模型:

class Sheker(models.Model):
    name = models.CharField(max_length=90)
    display_name = models.CharField(max_length=90, null=True)
    search_name = models.CharField(max_length=90, null=True)

    def __unicode__(self):
        return self.search_name


class Sod(models.Model):
    name = models.CharField(null=False, blank=False, max_length=100)
    sheker = models.ManyToManyField(Sheker, blank=True, name='sheker')

用一个简单的形式:

from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from rosh.models import *

class SodForm(forms.ModelForm):
    sheker = forms.ModelMultipleChoiceField(
        queryset=Sheker.objects.all(),
        widget=FilteredSelectMultiple("sheker", is_stacked=False),
        required=False
    )

模型Sheker 在数据库中有超过 12K 行(带有地理扩展的 postgres)-问题是它使表单加载超慢 = 加载 html 超过 5 秒。

问题是queryset=Sheker.objects.all()吗?我怎样才能让它加载得更快/缓存它或其他东西来快速加载页面(作为普通网页)。

解决此类问题的最佳做法是什么?

【问题讨论】:

虽然查询 12K 对象可能需要一段时间(“超级慢”到底是什么意思?)我猜,主要问题是在 html 模板上渲染 12K 行。你有没有考虑过用户体验?用户如何从 12K 选项列表中进行选择?您的方法还有其他替代方案吗? 哦,你有看过代码吗?来自 django 管理员的小部件 FilteredSelectMultiple 负责处理它。我会添加一些截图。 即使您使用 FliteredSelectMultiple 小部件,向用户提供 12K 选项供您选择也不是很友好。如果您可以以某种方式过滤列表(可能在获取列表之前询问用户一些问题),您可以使其更加用户友好并加快页面速度。 【参考方案1】:

如果查询执行的频率更高,您可以使用缓存数据库来保存值,那么这将是一个很好的解决方案。

如果页面经常使用,您可以缓存 [整个视图] (https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache),或者只是查询似乎适合您的应用程序。

您可以像这样缓存查询集结果:

from django.core.cache import cache
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from rosh.models import *

class SodForm(forms.ModelForm):

   # Check if the result is already cached
   sheker_results = cache.get('sheker_results'): # Returns None if not cached earlier

   # If the result is None, then query the database and set the cache
   if sheker_results is None:
       sheker_results = Sheker.objects.all()
       cahce.set('sheker_results',  sheker_results)

    sheker = forms.ModelMultipleChoiceField(
        queryset= sheker_results,
        widget=FilteredSelectMultiple("sheker", is_stacked=False),
        required=False
    )

post 描述了 django 中的缓存。

【讨论】:

【参考方案2】:

可能你可以在表单中设置字段自动补全,这样会减轻表单的负担,页面加载很快,字段只会从数据库中加载数据。

然后加速postgresql

【讨论】:

以上是关于Django form queryset=model.objects.all() 加载缓慢的主要内容,如果未能解决你的问题,请参考以下文章

修改django管理字段以使用特定的queryset和表单小部件

Django:将带有相关对象的 QuerySet 转换为 JSON

django queryset“包含”列表,而不是字符串

关于django form验证是否用户名已存在

Django Queryset - 按字母顺序排序,然后将特定条目移到顶部

django之Form组件一