我的模特之一特別複雜。當我嘗試在Django Admin中對其進行編輯時,它會執行1042個查詢並需要9秒的時間才能處理。如何強制Django Admin使用select_related?
我知道我可以用raw_id_fields
取代一些下拉菜單,但我認爲更大的瓶頸是它沒有執行select_related()
。
我可以得到管理網站來做到這一點嗎?
我的模特之一特別複雜。當我嘗試在Django Admin中對其進行編輯時,它會執行1042個查詢並需要9秒的時間才能處理。如何強制Django Admin使用select_related?
我知道我可以用raw_id_fields
取代一些下拉菜單,但我認爲更大的瓶頸是它沒有執行select_related()
。
我可以得到管理網站來做到這一點嗎?
對於我的特殊模型,特別緩慢的方面是通過ForeignKeys進行顯示時使用的形式顯示,這不是使用select_related
調用的,所以這是我要加快的部分。
通過相關Django的來源看,你在django/contrib/admin/options.py
看到formfield_for_foreignkeys
需要每個FK db_field
並調用ForeignKey
類的formfield
方法,它是在Django/DB /模型/場/與/像定義的方法:
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
提供)的自定義查詢集。
所以基本上我們想要做的是覆蓋admin.ModelAdmin
與SelectRelatedModelAdmin
,然後使我們的SelectRelatedModelAdmin
子類的ModelAdmin代替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)
此代碼示例不包括管理Inline
S或ManyToManyField
S,或foreign_key在由readonly_fields
或自定義select_related查詢調用的函數中遍歷,但類似的方法應該適用於這些情況。
雖然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')
queryset已重命名爲[get_queryset](https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset) – phoibos
這似乎不起作用**更改**頁面。也就是說,表單仍然有數千個查詢來獲取相關的實例。這僅僅是我,還是這對他人有用? django == 1.11.3 –
你可以試試這個
class Foo(admin.ModelAdmin):
list_select_related = (
'foreign_key1',
'foreign_key2',
)
不幸的是,我不認爲這解決了原始查詢。 「list_select_related」屬性用於管理員_listing_頁面,而不是對象_edit_頁面。當然,在我遇到同樣的問題時,使用列表相關設置不會加快編輯頁面,只有列表和選擇頁面。 –
這可以通過'get_field_queryset'被簡化(雖然它是無證,因此可以在未來改變)。 –