为什么Django admin list_select_related在这种情况下不起作用?

Ben*_*oyt 10 python django performance django-admin

我有一个ModelAdmin包含外键字段的类list_display.但该模型的管理列表页面正在执行数百个查询,每行一个查询以从另一个表中获取数据而不是join(select_related()).

Django文档表明你可以list_select_related = True作为属性添加到你的ModelAdmin中以使其消失,但它似乎对我来说根本不起作用.这个问题似乎也提出了类似的问题,但他的解决方案尚不清楚,而且在我的案例中也不起作用.

这是我的模型和模型管理员的简化版本:

class Device(models.Model):
    serial_number = models.CharField(max_length=80, blank=True, unique=True)
    label = models.CharField(max_length=80, blank=True)

    def __str__(self):
        s = str(self.serial_number)
        if self.label:
            s += ': {0}'.format(self.label)
        return s

class Event(models.Model):
    device = models.ForeignKey(Device, null=True)
    type = models.CharField(max_length=40, null=False, blank=True, default='')

class EventAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'device')
    list_select_related = True
Run Code Online (Sandbox Code Playgroud)

但是,添加它list_selected_related = True并没有改变任何东西.我仍然得到很多像这样的查询而不是SQL连接:

很多查询,而不是连接

任何想法为什么Django管理员似乎忽略我的list_select_related和做N查询?我正在使用Python 2.7和Django 1.3.3.

Dan*_*man 15

这里的问题是,设置list_select_related = True只是select_related()在查询中添加了一个基本内容,但默认情况下该调用不遵循ForeignKeys null=True.所以答案是定义changelist自己使用的查询集,并指定要遵循的FK:

class EventAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'device')
    def queryset(self, request):
        return super(EventAdmin, self).queryset(request).select_related('device')
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!外键上的`null = True`肯定会阻止selected_related做它的事情.我想如果我一直跟着[docs](https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_related),我已经看到:"请注意,默认情况下,select_related()不遵循具有null = True的外键" (2认同)
  • 在Django> = 1.6中,该方法现在名为`get_queryset`. (2认同)

Fus*_*ush 7

从Django 1.6开始,list_select_related接受一个布尔,列表或元组,其中包含要包含在select_related()调用中的字段的名称.因此,您现在可以使用:

class EventAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'device')
    list_select_related = ['device']
Run Code Online (Sandbox Code Playgroud)