具有内联模型的Django管理页面加载速度非常慢

时间:2017-04-26 16:57:10

标签: django django-admin

我有一个带有单个内联模型的模型的Django管理页面。当内联模型有许多项目(如75)时,页面加载速度非常慢(大约30秒)。即使我排除了内联模型中的所有字段,只需渲染名称,也是如此。删除内联模型会导致页面加载速度非常快(以秒为单位)。

如何让此页面加载更快?

2 个答案:

答案 0 :(得分:9)

您可以采取两项措施来加快此页面的加载速度。

  1. 设置DEBUG = False
  2. 缓存在内联模型呈现中使用的数据库查询。
  3. 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
    

答案 1 :(得分:0)

在此处查看我的解决方案:https://stackoverflow.com/a/51391915/1496567

我的管理类如下:

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, )