如何强制 Django Admin 使用 select_lated?
我的一个模型特别复杂。当我尝试在 Django Admin 中编辑它时,它执行 1042 个查询,处理时间超过 9 秒。
我知道我可以用 raw_id_fields
替换一些下拉菜单,但我认为更大的瓶颈是它没有执行应有的 select_lated()
。
我可以通过管理网站来执行此操作吗?
One of my models is particularily complex. When I try to edit it in Django Admin it performs 1042 queries and takes over 9 seconds to process.
I know I can replace a few of the drop-downs with raw_id_fields
, but I think the bigger bottleneck is that it's not performing a select_related()
as it should.
Can I get the admin site to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
为了完整起见,我想添加另一个最适合我的用例的选项。
正如其他人指出的那样,问题通常是加载选择框的数据。
list_select_lated
在这种情况下没有帮助。如果您实际上不想通过管理员编辑外键字段,最简单的解决方法是将相应字段设为只读:
您仍然可以显示这些字段,只是没有选择框,因此 Django 不需要检索数据库中的所有选择框选项。
For the sake of completeness, I would like to add another option that was the most suitable for my use case.
As others have pointed out, the problem is often loading the data for select boxes.
list_select_related
does not help in this case.In case you don't actually want to edit the foreign key field via admin, the easiest fix is making the respective field readonly:
You can still display these fields, there will simply not be a select box, hence Django does not need to retrieve all the select box options from the database.
你可以尝试这个
https:// docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_select_lated
you can try this
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_select_related
虽然 jimbob 博士的回答是有道理的,但根据我的需要,我能够简单地用一行代码重写 get_queryset() 方法,甚至选择外键的外键。也许这对某人有帮助。
Although dr jimbob's answer makes sense, for my needs, I was able to simply override the get_queryset() method with a one-liner, even selecting a foreign key's foreign key. Maybe this could be helpful to someone.
对于我的特定模型,特别慢的方面是在表单中显示外键时,它们不会使用
select_lated
调用,所以这就是我要加快的部分。查看相关的 django 源代码,您可以在
django/contrib/admin/options.py
中看到方法formfield_for_foreignkeys
获取每个 FKdb_field
并调用ForeignKey
类的formfield
方法,该方法定义在 django/db/models/fields/lated/ 中,如下所示:由此,我们看到是否我们为
db_field
提供kwargs['queryset']
我们可以定义一个将使用 select_lated 的自定义查询集(这可以由formfield_for_foreignkey
提供>)。所以基本上我们想要做的是用
SelectRelatedModelAdmin
覆盖admin.ModelAdmin
,然后使我们的 ModelAdmin 子类为SelectRelatedModelAdmin
而不是admin 。 ModelAdmin
此代码示例不涵盖 admin
Inline
或ManyToManyField
,或由 调用的函数中的foreign_key 遍历readonly_fields 或自定义 select_lated 查询,但类似的方法应该适用于这些情况。For my particular model, the particularly slow aspect is going through ForeignKeys when they were being displayed in forms, which aren't called using
select_related
, so that's the part I'm going to speed up.Looking through the relevant django source, you see in
django/contrib/admin/options.py
that the methodformfield_for_foreignkeys
takes each FKdb_field
and calls theForeignKey
class'sformfield
method, which is defined in django/db/models/fields/related/ like:From this, we see if we provide the
db_field
with akwargs['queryset']
we can define a custom queryset that will be use select_related (this can be provided byformfield_for_foreignkey
).So basically what we want to do is override
admin.ModelAdmin
withSelectRelatedModelAdmin
and then make our ModelAdmin subclasses ofSelectRelatedModelAdmin
instead ofadmin.ModelAdmin
This code sample doesn't cover admin
Inline
s orManyToManyField
s, or foreign_key traversal in functions called byreadonly_fields
or custom select_related queries, but a similar approach should work for those cases.在 Django 2.0+ 中,提高外键和多对多关系性能的一个好方法是使用 自动完成字段。
这些字段不显示所有相关对象,因此加载的查询要少得多。
In Django 2.0+, a good way to improve performance of ForeignKey and ManyToMany relationships is to use autocomplete fields.
These fields don't show all related objects and therefore load with many fewer queries.
对于管理员编辑/更改特定项目页面,外键选择框可能需要很长时间才能加载,以改变 django 查询外键数据的方式:
有关使用的 Django 文档formfield_for_foreignkey
假设我的
Example
模型上有一个名为foo
的字段,并且我希望选择相关的bar
对象:For the admin edit/change a specific item page, foreign key select boxes may take a long time to load, to alter the way django queries the data for the foreign key:
Django docs on Using formfield_for_foreignkey
Say I have a field called
foo
on myExample
model, and I wish to select ralatedbar
objects: