对于我的特定模型,特别慢的方面是当 ForeignKeys 显示在表单中时,它们不是使用 select_related 调用的,所以这就是我要加快速度的部分。
查看相关的django源码,你在django/contrib/admin/options.py看到方法formfield_for_foreignkeys接受每个FK db_field并调用ForeignKey类的formfield方法,该方法定义在django/db/models/领域/相关/喜欢:
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)
由此,我们看看是否为db_field 提供kwargs['queryset'],我们可以定义一个将使用select_related 的自定义查询集(这可以由formfield_for_foreignkey 提供)。
所以基本上我们想要做的就是用SelectRelatedModelAdmin 覆盖admin.ModelAdmin,然后将我们的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)
此代码示例不包括 admin Inlines 或 ManyToManyFields,或由 readonly_fields 或自定义 select_related 查询调用的函数中的 foreign_key 遍历,但类似的方法应该适用于这些情况。