【问题标题】:Speeding Up the Django Admin Delete Page加速 Django 管理员删除页面
【发布时间】:2011-08-20 12:26:34
【问题描述】:

您将如何加快 Django Admin 记录删除操作/页面的速度?

我有一个模型 B,它对模型 A 有一个外键约束。对于 A 中的每条记录,B 中大约有 10k 条记录绑定到 A。因此,当我必须使用默认的“删除已选择”删除 A 中的记录时admin 中的“A”操作,Django 将花费 15 分钟查询并显示 B 中被删除的每条记录。我将如何修改它,而不是列出数千个依赖对象,它只显示被删除的依赖对象的计数?

【问题讨论】:

    标签: python django django-admin django-orm


    【解决方案1】:

    像往常一样浏览 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 数据库上进行简单的时间测试,我发现使用 qs.delete() 删除约 150 个没有事务的对象需要 11.3 秒,使用 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

    【讨论】:

    • 这会有所帮助——但另一个大问题是在 django.contrib.admin.actions.py 中调用 get_deleted_objects (django 1.4 中的第 34 行)。在此编译对象的完整层次结构,以便稍后在模板中显示。这至少是我的代码挂起的地方。希望这也有帮助。
    【解决方案2】:

    对于 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 %} 
    

    【讨论】: