加快Django后台删除页面速度

6 投票
2 回答
2530 浏览
提问于 2025-04-16 17:09

如何加快Django后台删除记录的速度?

我有一个模型B,它和模型A有外键关系。也就是说,模型A中的每一条记录大约都有1万条记录在模型B中与之关联。所以当我在后台使用默认的“删除选中的A”操作来删除A中的一条记录时,Django需要花15分钟来查询并显示所有要删除的B中的记录。有没有办法修改这个过程,让它只显示要删除的关联记录的数量,而不是列出成千上万的记录?

2 个回答

1

对于Django 1.4版本,@drjimbob提供的做法稍微有点不同:

更新这个文件:

django/contrib/admin/templates/admin/delete_selected_confirmation.html

然后在第35行,把

{% for deletable_object in deletable_objects %}
    <ul>{{ deletable_object|unordered_list }}</ul>
{% endfor %}

替换成

{% for deletable_object in deletable_objects %}
    {% if 100 < deletable_object|length %}
        <p>{{ deletable_object|length }} objects</p>
    {% else %}
        <ul>{{ deletable_object|unordered_list }}</ul>
    {% endif %}
{% endfor %} 
10

像往常一样,可以查看Django的源代码来找到你的答案(其实它的代码很容易读懂,变量、函数、类和文件的命名都很有逻辑)。

看一下 django/contrib/admin/templates/admin/delete_confirmation.html(在Django 1.2.5版本中),你会发现第24行包含了:

<ul>{{ deleted_objects|unordered_list }}</ul>

如果你把它改成

<p>{{ deleted_objects|count }} objects</p>

或者

{% if 100 < deleted_objects|count %}
    <p>{{ deleted_objects|count }} objects</p>
{% else %}
    <ul>{{ deleted_objects|unordered_list }}</ul>
{% endif %}

这样的话,它只会显示被删除对象的数量(如果删除的对象很多的话)。

你可能还想试着编辑 django/contrib/admin/templates/admin/actions.py,使用SQL事务来更快地进行批量删除。可以参考这个链接:http://docs.djangoproject.com/en/dev/topics/db/transactions/

简单来说,action.py现在的工作方式是形成一个合适的查询集,然后直接调用delete()来删除这些对象,但没有把这些操作放在一个数据库事务中。通过在一个示例的sqlite数据库上做简单的时间测试,我发现不使用事务删除大约150个对象需要11.3秒,使用 qs.delete() 是13.4秒,而使用 for obj in qs: obj.delete() 则是13.4秒。使用事务(在删除函数前加上 @transaction.commit_on_success),同样的命令只需要0.35秒和0.39秒(快了大约30倍)。当然,使用事务可能会暂时锁定数据库,这可能不是一个可接受的选择。

如果想合理地扩展Django的管理界面(通常你不想直接编辑源代码;特别是当其他用户也在使用相同的文件,或者你可能想以后恢复原样,或者在同一台机器上运行其他Django网站时),可以查看这个链接:http://www.djangobook.com/en/1.0/chapter17/#cn35

撰写回答