我有一个Django管理页面,其中包含一个单一的嵌入模型。当嵌入模型有许多条目(例如75个)时,页面加载非常缓慢(大约需要30秒)。即使我在内联模型上排除所有字段,只渲染名称,这也是正确的。移除内嵌模型可以使页面快速加载(几秒钟内)。
我该如何让这个页面加载更快?
我该如何让这个页面加载更快?
有两个方法可以加快此页面的加载速度:
DEBUG = False
。此页面加载缓慢的原因是 Django 管理员为每个内联模型实例呈现子模板。即使其中内容很少,75 个内联模型实例会呈现 75 个额外的模板。虽然渲染模板通常非常快,但如果您使用了 DEBUG = True
,则对于您呈现的每个模板,都会产生额外的开销,因为 Django 会注入用于其调试模式错误页面的额外上下文(在我的系统上每个模板约为 0.4 秒)。这种额外开销通常不会引起注意,因为您通常只会为单个页面呈现少量模板。但是,当您呈现 75 个模板时,这加起来就会导致明显的延迟(75 * 0.4 秒 = 30 秒)。
至少在 Django 1.10 中,内联模型将为每个内联模型实例进行任何必要的数据库查询以呈现它。如果您的内联模型具有内联模型上的任何外键,则在具有缓慢的数据库连接时,这可能会非常低效。技巧是在初始化内联类的实例(使用 get_formsets_with_inlines
)时运行用于这些外键选择的数据库查询,然后将这些字段的选择项替换为缓存值,以防止重复此数据库查询(使用formfield_for_foreignkey
)。
class Manufacturer(models.Model):
...
class OperatingSystem(models.Model):
...
class Computer(models.Model):
manufacturer = models.ForeignKey(Manufarturer)
owner = models.ForeignKey(User)
operating_system = models.ForeignKey(OperatingSystem)
...
class ComputerAdmin(admin.StackedInline):
model = Computer
def formfield_for_foreignkey(self, db_field, request, **kwargs):
field = super(ComputerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == "owner" and hasattr(self, "cached_owners"):
field.choices = self.cached_owners
elif db_field.name == "manufacturer" and hasattr(self, "cached_manufacturers"):
field.choices = self.cached_manufacturers
elif db_field.name == "operating_system" and hasattr(self, "cached_operating_systems"):
field.choices = self.cached_operating_systems
return field
class ManufacturerAdmin(admin.ModelAdmin):
inlines = (ComputerAdmin,)
def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
inline.cached_owners = [(i.pk, str(i)) for i in User.objects.all()]
inline.cached_manufacturers = [(i.pk, str(i)) for i in Manufacturer.objects.all()]
inline.cached_operating_systems = [(i.pk, str(i)) for i in OperatingSystem.objects.all()]
yield inline.get_formset(request, obj), inline
请查看我的解决方案:https://dev59.com/sl0b5IYBdhLWcg3wENmK#51391915
我的管理员类如下所示:
class ItemBazarInlineAdmin(AdminInlineWithSelectRelated):
model = ItemBazar
list_select_related = (
'alumno_item__alumno__estudiante__profile',
'alumno_item__item__anio_lectivo',
'comprobante__forma_pago',
)
class ComprobanteAdmin(AdminWithSelectRelated):
list_display = ('__str__', 'total', 'estado', 'fecha_generado', 'forma_pago', 'tipo', )
list_filter = ('estado', 'forma_pago', )
list_select_related = ('forma_pago', )
inlines = (ItemServicioInlineAdmin, )