mpe*_*pen 24 django django-models django-orm django-admin
我的一个模型特别复杂.当我尝试在Django Admin中编辑它时,它执行1042个查询并花费超过9秒来处理.
我知道我可以替换掉一些下拉菜单raw_id_fields,但我认为更大的瓶颈在于它没有表现出select_related()应有的效果.
我可以让管理网站这样做吗?
Clo*_*ans 32
虽然jimbob博士的回答是有道理的,但根据我的需要,我能够简单地用一行代替覆盖get_queryset()方法,甚至可以选择外键的外键.也许这对某人有帮助.
class MyModelAdmin(admin.ModelAdmin):
model = MyModel
...
def get_queryset(self, request):
return super(MyModelAdmin, self).get_queryset(request).select_related(
'foreign_key1', 'foreign_key2__fk2_foreign_key')
Run Code Online (Sandbox Code Playgroud)
小智 20
你可以试试这个
class Foo(admin.ModelAdmin):
list_select_related = (
'foreign_key1',
'foreign_key2',
)
Run Code Online (Sandbox Code Playgroud)
dr *_*bob 11
对于我的特定模型,当它们以表格形式显示时,特别慢的方面是通过ForeignKeys,而不是使用select_related,这是我要加速的部分.
通过查看相关的django源代码,您会看到django/contrib/admin/options.py 该方法formfield_for_foreignkeys采用每个FK db_field并调用ForeignKey类的 formfield方法,该方法在django/db/models/fields/related/like中定义:
def formfield(self, **kwargs):
db = kwargs.pop('using', None)
defaults = {
'form_class': forms.ModelChoiceField,
'queryset': self.rel.to._default_manager.using(db).complex_filter(self.rel.limit_choices_to),
'to_field_name': self.rel.field_name,
}
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)
Run Code Online (Sandbox Code Playgroud)
从这里,我们看到我们是否提供了db_field一个kwargs['queryset']我们可以定义一个将使用select_related的自定义查询集(这可以由提供formfield_for_foreignkey).
所以基本上我们想要做的是覆盖admin.ModelAdmin,SelectRelatedModelAdmin然后使用我们的ModelAdmin子类SelectRelatedModelAdmin而不是admin.ModelAdmin
class SelectRelatedModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if 'queryset' in kwargs:
kwargs['queryset'] = kwargs['queryset'].select_related()
else:
db = kwargs.pop('using', None)
kwargs['queryset'] = db_field.rel.to._default_manager.using(db).complex_filter(db_field.rel.limit_choices_to).select_related()
return super(SelectRelatedModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Run Code Online (Sandbox Code Playgroud)
此代码示例不包括admin Inline或ManyToManyFields,或者在调用的函数readonly_fields 或自定义select_related查询中的foreign_key遍历,但类似的方法应该适用于这些情况.
对于管理员编辑/更改特定项目页面,外键选择框可能需要很长时间才能加载,以改变 django 查询外键数据的方式:
关于使用 formfield_for_foreignkey 的 Django 文档
foo假设我的模型有一个调用的字段Example,并且我希望选择相关bar对象:
class ExampleAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "foo":
kwargs["queryset"] = Example.objects.select_related('bar')
return super().formfield_for_foreignkey(db_field, request, **kwargs)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12394 次 |
| 最近记录: |