Đối với mô hình cụ thể của tôi, khía cạnh đặc biệt chậm đi qua ForeignKeys khi chúng được hiển thị dưới dạng, không được gọi là sử dụng select_related
, vì vậy đó là phần tôi sẽ tăng tốc.
Nhìn qua các nguồn django có liên quan, bạn sẽ thấy trong django/contrib/admin/options.py
rằng phương pháp formfield_for_foreignkeys
mất mỗi FK db_field
và gọi ForeignKey
phương pháp formfield
lớp, được định nghĩa trong django/db/mô hình/lĩnh vực/liên quan/như:
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)
Từ điều này, chúng tôi thấy nếu chúng tôi cung cấp db_field
với kwargs['queryset']
, chúng tôi có thể xác định bộ truy vấn tùy chỉnh sẽ sử dụng select_related (điều này có thể được cung cấp bởi formfield_for_foreignkey
).
Vì vậy, về cơ bản những gì chúng tôi muốn làm là ghi đè admin.ModelAdmin
với SelectRelatedModelAdmin
và sau đó làm cho lớp con ModelAdmin của chúng ta về SelectRelatedModelAdmin
thay vì 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)
mẫu mã này không bao gồm quản trị Inline
s hoặc ManyToManyField
s, hoặc foreign_key traversal trong các hàm được gọi là readonly_fields
hoặc truy vấn select_related tùy chỉnh, nhưng cách tiếp cận tương tự sẽ hoạt động đối với những trường hợp đó.
Điều này có thể được đơn giản hóa bởi 'get_field_queryset' (mặc dù nó là không có giấy tờ và do đó có thể thay đổi trong tương lai). –