11

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

Django 文档表明您可以将list_select_related = True其作为属性添加到您的 ModelAdmin 以使其消失,但它似乎对我来说根本不起作用。这个 SO question似乎给出了类似的问题,但他的解决方案尚不清楚,并且在我的情况下不起作用。

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

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

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

很多查询,而不是连接

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

4

3 回答 3

18

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

class EventAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'device')
    def queryset(self, request):
        return super(EventAdmin, self).queryset(request).select_related('device')
于 2013-03-04T22:13:14.863 回答
10

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

class EventAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'device')
    list_select_related = ['device']
于 2015-02-25T03:52:04.273 回答
0

虽然select_related通常是要走的路,但有时需要更多控制,然后覆盖get_queryset变得更适用,这是丹尼尔罗斯曼答案的更现代版本:

外键字段在哪里foo和是:bar

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('foo', 'foo__bar').only('foo__field1', 'foo__bar__field2')
于 2020-11-04T14:45:16.093 回答