如何加速Django Admin记录删除操作/页面?
我有一个模型B,它与模型A有外键约束。对于A中的每条记录,都有约10k条记录绑定到A的B。因此,当我使用默认的"删除所选A"操作在管理界面中删除A中的一条记录时,Django将花费15分钟来查询和显示正在被删除的每个B记录。我该如何修改它,使其只显示正在被删除的相关对象数量,而不是列出数千个相关对象?
如何加速Django Admin记录删除操作/页面?
我有一个模型B,它与模型A有外键约束。对于A中的每条记录,都有约10k条记录绑定到A的B。因此,当我使用默认的"删除所选A"操作在管理界面中删除A中的一条记录时,Django将花费15分钟来查询和显示正在被删除的每个B记录。我该如何修改它,使其只显示正在被删除的相关对象数量,而不是列出数千个相关对象?
像往常一样,浏览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()
和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/templates/admin/delete_selected_confirmation.html
{% for deletable_object in deletable_objects %}
<ul>{{ deletable_object|unordered_list }}</ul>
{% endfor %}
for
{% 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 %}