加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – Django – 查询重复/低效

发布时间:2020-12-20 12:35:42 所属栏目:Python 来源:网络整理
导读:好吧,我有一个Django视图,像这样: @render_to('home/main.html')def login(request): # also tried Client.objects.select_related().all() clients = Client.objects.all() return {'clients':clients} 我有一个模板,main.html,像这样: ul{% for client i
好吧,我有一个Django视图,像这样:

@render_to('home/main.html')
def login(request):
    # also tried Client.objects.select_related().all()
    clients = Client.objects.all()
    return {'clients':clients}

我有一个模板,main.html,像这样:

<ul>
{% for client in clients %}
<li>{{ client.full_name }}</li>
    <ul>
    {% for pet in client.pets.all %}
        <li>{{ pet.full_name }}</li>
    {% endfor %}
    </ul>
{% endfor %}
</ul>

我还打印出基础模板底部的sql_queries中的所有查询.运行此视图时,将进行以下查询:

SELECT `home_client`.`id`,... FROM `home_client`;
SELECT `home_pet`.`id`,... FROM `home_pet` WHERE `home_pet`.`client_id` = 1;
SELECT `home_client`.`id`,... FROM `home_client` WHERE `home_client`.`id` = 1;
SELECT `home_client`.`id`,... FROM `home_client` WHERE `home_client`.`id` = 1;
SELECT `home_pet`.`id`,... FROM `home_pet` WHERE `home_pet`.`client_id` = 2;
SELECT `home_client`.`id`,... FROM `home_client` WHERE `home_client`.`id` = 2;

我的问题是,为什么要进行所有这些查询?它不应该只是1个查询来检索所有客户端和每个客户端的查询以从每个客户端检索所有宠物?我在home_client表中有2个客户端,所以总共应该有3个查询.最令人不安的是查询3和4是100%相同的.我不想“过早地优化”或任何其他东西,但我确实希望确保Django的效率不高.任何有关这方面的帮助将不胜感激.谢谢.

解决方法

客户1有2个宠物,而客户2有1个宠物吗?

如果是这样,那将告诉我Pet.full_name或您在Pet显示循环中正在做的其他事情正在尝试访问其相关客户端的详细信息. Django的ORM不使用identity map,因此从任何Pet对象访问Client外键都需要再次访问数据库以检索该Client.

附: select_related对您在此场景中使用的数据没有任何影响,因为它只遵循外键关系,但宠物与客户的关系是多对一的.

更新:如果你想避免更改Pet.full_name中的逻辑或者必须在模板中执行所述逻辑而不是这种情况,你可以改变你在每个客户的宠物上获得句柄的方式,以便预先填写ForeignKey缓存与每个宠物与其客户:

class Client(models.Model):
    # ...
    def get_pets(self):
        for pet in self.pets.all():
            setattr(pet,'_client_cache',self)
            yield pet

…’_client_cache’的’client’部分是Pet的类中用于PetK客户端的ForeignKey的属性名称.这利用了Django使用SingleRelatedObjectDescriptor类实现对ForeignKey相关对象的访问的方式,该类在查询数据库之前查找此缓存属性.

结果模板用法:

{% for pet in client.get_pets %}
...
{% endfor %}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读