私のモデルの1つは特に複雑です。 Django Adminで編集しようとすると、1042クエリが実行され、処理に9秒以上かかります。
ドロップダウンのいくつかを_raw_id_fields
_に置き換えることができることは知っていますが、より大きなボトルネックは、select_related()
が正常に実行されていないことだと思います。
管理サイトにこれを実行させることはできますか?
Dr 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')
あなたはこれを試すことができます
class Foo(admin.ModelAdmin):
list_select_related = (
'foreign_key1',
'foreign_key2',
)
私の特定のモデルでは、フォームに表示されているときにForeignKeysを通過するのが特に遅いので、select_related
を使用して呼び出されないので、これを高速化します。
関連するDjangoソースを見ると、Django/contrib/admin/options.py
でメソッドformfield_for_foreignkeys
が各FKdb_field
を受け取り、ForeignKey
クラスを呼び出すことがわかります。 formfield
メソッド。Django/ db/models/fields/related /で定義されています。
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
でオーバーライドしてから、ModelAdminサブクラスをadmin.ModelAdmin
ではなくSelectRelatedModelAdmin
にします。
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 Inline
sまたはManyToManyField
s、またはreadonly_fields
またはカスタムselect_relatedクエリによって呼び出される関数のforeign_keyトラバーサルをカバーしていませんが、同様のアプローチがこれらの場合に機能するはずです。
Django 2.0+では、ForeignKeyとManyToManyの関係のパフォーマンスを向上させる良い方法は、 オートコンプリートフィールド を使用することです。
これらのフィールドには、関連するすべてのオブジェクトが表示されるわけではないため、より少ないクエリで読み込まれます。