当我加载菜单标签时,我有很多重复的查询(在django调试工具栏中),我确定我可以优化这个但是找不到好方法。
模特:
def page(request):
categs = Categorie.objects.filter(visible = True)
return render(request, 'page.html', locals())
观点:
{% for categ in categs %}
<li>
{{categ.name}}
<ul>
{% for scateg in categ.getscateg %}
<li>
{{scateg.name}}
<ul>
{% for theme in scateg.gettheme %}
<li>{{ theme.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
模板:
function listener()
{
console.debug("listener fired.");
}
document.addEventListener('DOMSubtreeModified', function() {
var iframes = document.getElementsByTagName("iframe");
for (var i = 0, len = iframes.length, doc; i < len; ++i) {
// Catch and ignore errors caused by iframes from other domains
console.log(i);
try {
doc = iframes[i].contentDocument || iframes[i].contentWindow.document;
//console.log(doc);
doc.addEventListener("DOMSubtreeModified", listener, true);
} catch (ex) { console.log(ex); }
}
},false);
我看看prefetch_related但只有在我想要从SousCategorie加载分类和SousCategorie主题时才有效,所以如果我理解我需要与此相反......
答案 0 :(得分:2)
解决了!
如果可以提供帮助:
from .models import Categorie, SousCategorie, Theme, SousTheme
from django.db.models import Prefetch
pf_souscategorie = Prefetch('souscategorie_set', SousCategorie.objects.filter(visible=True))
pf_theme = Prefetch('souscategorie_set__theme_set', Theme.objects.filter(visible=True))
pf_soustheme = Prefetch('souscategorie_set__theme_set__soustheme_set', SousTheme.objects.filter(visible=True))
categs = Categorie.objects.filter(visible=True).prefetch_related(pf_souscategorie, pf_theme, pf_soustheme)
并在模板中调用如下:
{% with currscat=categ.souscategorie_set.all %}
{% with currth=souscateg.theme_set.all %}
{% with currsth=theme.soustheme_set.all %}
再见
答案 1 :(得分:0)
在Django中,每次评估新查询集时都会执行查询,因此需要减少正在使用的查询集的数量。以下是发生的事情:
Categorie.objects.filter(visible=True)
并将其传递到视图层,第一个查询将在此标记{% for categ in categs %}
categ.getscateg
的每个类别,它返回一个新的查询集return self.souscategorie_set.all().filter(visible = True)
,此查询集将在模板{% for scateg in categ.getscateg %}
<的第二个循环中执行/ LI>
{% for theme in scateg.gettheme %}
使用prefetch_related
是正确的举动,尝试类似(没有测试它):
Categorie.objects.filter(visible=True, souscategorie_set__visible=True, souscategorie_set__theme_set__visible=True).prefetch_related('souscategorie_set__theme_set')
prefetch_related
通过运行第一个查询来加载满足当前过滤器的类别,然后执行第二个查询来加载所有子类别,依此类推。
在其他情况下,您可以使用select_related
,但这仅适用于可以使用单个查询的情况,例如,如果您需要主题的类别和子类别,它将起作用,如:
Theme.objects.filter(pk=1).select_related('souscategorie__categorie')
这里的区别在于主题是具有ForeignKey
的主题,因此它只有一个子类别,并且可以加载单个联接,这意味着只有在select_related
时才能使用OneToOneField
您的查询集来自指向的模型,我认为它也适用于"scripts": {
"info": "echo 'npm as a build tool'",
"installBashPlugin": "echo 'source ~/.bash_plugins/.my_plugin' >> ~/.bash_profile"
。
答案 2 :(得分:0)
我使用“with”
将查询集减少了2这是一个好点,但我总是有很多重复(例如51个重复的51个查询),例如,当我这样做时,我点击了我的数据库:
{% for categ in categs %}
{% with currscat=categ.getscateg %}
<li class = "{% if currscat %} has_menu {% endif %}"> {{categ.name}} # This line hit database
{% if currscat %} # This line hit database
<ul class = "menu-1"> ... </ul>
{% endif %}
</li>
{% endwith %}
{% endfor %}
我尝试使用prefetch_related,如下所示:
categs = Categorie.objects.filter(visible=True).prefetch_related('souscategorie_set')
但那只是向数据库添加查询,不要减少......
一些建议?
由于