gpt4 book ai didi

python - 糟糕的 Django 管理性能

转载 作者:行者123 更新时间:2023-12-01 01:39:20 25 4
gpt4 key购买 nike

我正在开发一个 Django 项目,该项目已经获得了大量的真实世界数据,因此我可以看到它的性能。

少数 DjangoAdmin 列表的性能非常糟糕。

我有一个管理列表,我们称之为 devices 。在该列表中,我为每一行获取附加信息,这些字段与其他表相关并通过 FK/PK/M2N 连接。

列表包含大约 500 条记录,根据 django-debug-toolbar 加载该屏幕需要花费时间。 ,大约6.5秒,令人难以忍受。

该管理类

@admin.register(Device)
class DeviceAdmin(admin.ModelAdmin):
list_select_related = True
list_display = ('id', 'name', 'project', 'location', 'machine', 'type', 'last_maintenance_log')
inlines = [CommentInline, TestLogInline]

def project(self, obj):
try:
return Device.objects.get(pk=obj.pk).machine.location.project.project_name
except AttributeError:
return '-'

def location(self, obj):
try:
return Device.objects.get(pk=obj.pk).machine.location.name
except AttributeError:
return '-'

def last_maintenance_log(self, obj):
try:
log = AdminLog.objects.filter(object_id=obj.pk).latest('time')
return '{} | {}'.format(log.time.strftime("%d/%m/%Y, %-I:%M %p"), log.title)
except AttributeError:
return '-'

全部Machine , LocationProject是数据库中的表。

查看 django-debug-toolbar 中的查询后我发现了一些可怕的事情。该屏幕需要 287 个 SQL 查询!是的,超过两百个!

我可以做些什么来将这个时间缩短到合理的范围内吗?

编辑:感谢布鲁诺,我删除了 Device.objects.get(pk=obj.id) (因为它确实是多余的,所以我完全忽略了这一点。

所以我把 obj. 放在任何地方例如obj.machine.location.project.project_name

仅此一项就可以将速度和查询数量降低一半,到目前为止还不错。

我在融合 obj 时没有遇到问题方法和select_related方法。这是我当前的代码,比 obj 更糟糕方法。

def project(self, obj):
try:
Device.objects.select_related('machine__location__project').get(id=obj.pk).machine.location.project.project_name
except AttributeError:
return '-'

这在查询中创建了一个很好的 INNER JOIN,但性能比没有它并且仅使用 obj.machine.location.project.project_name 差大约 15%

我做错了什么?

编辑2:

我获得的最佳性能是使用以下代码:

@admin.register(Device)
class DeviceAdmin(admin.ModelAdmin):
list_select_related = True
save_as = True
form = DeviceForm
list_display = ('id', 'name', 'project', 'location', 'machine', 'type', 'last_maintenance_log')
inlines = [CommentInline, TestLogInline]

def project(self, obj):
try:
return obj.machine.location.project.project_name
except AttributeError:
return '-'

def location(self, obj):
try:
return obj.machine.location.name
except AttributeError:
return '-'

def last_maintenance_log(self, obj):
try:
log = AdminLog.objects.filter(object_id=obj.pk).latest('time')
return '{} | {}'.format(log.time.strftime("%d/%m/%Y, %-I:%M %p"), log.title)
except AttributeError:
return '-'

def get_queryset(self, request):
return Device.objects.select_related('machine__location__project').all()

这将查询次数从近 300 次减少到 104 次,时间减少了 50% 以上。可以进一步改进吗?

最佳答案

首先,避免完全无用的查询 - 这:

Device.objects.get(pk=obj.pk)

因为 obj 已经是您正在寻找的 Device 实例而毫无用处。

然后override your DeviceAdmin.get_queryset method正确使用select_relatedprefetch_related因此您只有所需的最少查询数量。

关于python - 糟糕的 Django 管理性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52056456/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com