2013-03-04 213 views
9

我有一個ModelAdmin類,它的list_display包含一個外鍵字段。但該模型的管理列表頁面正在執行數百個查詢,每行一個查詢以從另一個表中獲取數據而不是連接(select_related())。爲什麼Django admin list_select_related在這種情況下不起作用?

Django文檔indicate您可以將list_select_related = True作爲屬性添加到您的ModelAdmin中,以使其消失,但對我而言似乎不起作用。 This 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的聯接:

Lots of queries, not a join

任何想法,爲什麼Django管理似乎無視我的list_select_related和做N次查詢?我使用Python 2.7和Django 1.3.3。

回答

14

問題在於設置list_select_related = True只是在查詢上添加了一個基本的select_related(),但該調用默認情況下不會跟隨ForeignKeys與null=True。因此,答案是確定變更列表使用自己的查詢集,並指定FK遵循:

class EventAdmin(admin.ModelAdmin): 
    list_display = ('__str__', 'device') 
    def queryset(self, request): 
     return super(EventAdmin, self).queryset(request).select_related('device') 
+2

謝謝!外鍵上的'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的外鍵」「 – 2013-03-04 23:00:46

+0

出於興趣,你知道爲什麼'list_select_related = True'不是Django的默認值管理員?這似乎是一個更明智的默認。 (我可以明白爲什麼默認'select_related()'不遵循具有null = True的外鍵,因爲這可能是一個性能問題,但我想知道其他情況下的'list_select_related'。) – 2013-03-10 20:54:57

+0

在Django> = 1.6該方法現在被命名爲'get_queryset'。 – TAH 2017-07-29 19:29:10

6

Since Django 1.6list_select_related接受一個布爾值,列表或元組與字段的名稱在select_related()調用包括。 因此您現在可以使用:

class EventAdmin(admin.ModelAdmin): 
    list_display = ('__str__', 'device') 
    list_select_related = ['device'] 
相關問題