需要一些重复查询的建议

时间:2015-10-31 20:01:13

标签: django django-queryset

当我加载菜单标签时,我有很多重复的查询(在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主题时才有效,所以如果我理解我需要与此相反......

3 个答案:

答案 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') 

但那只是向数据库添加查询,不要减少......

一些建议?

由于