2013-03-04 21 views
9

Mam klasę ModelAdmin, która zawiera pole klucza obcego w numerze list_display. Ale strona z listą administratorów dla tego modelu wykonuje setki zapytań, jedno zapytanie w wierszu, aby uzyskać dane z drugiej tabeli zamiast łączenia (select_related()).Dlaczego administrator Django element_zestawu_related nie działa w tym przypadku?

Django docs indicate możesz dodać list_select_related = True jako atrybut do swojego ModelAdmin, aby to zniknęło, ale nie wydaje mi się, że działa. This SO question wydaje się dawać podobny problem, ale jego rozdzielczość jest niejasna i nie działa w moim przypadku.

Oto wersja cut-dół mojego modelu i modelu administratora:

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 

jednak dodać, że list_selected_related = True niczego nie zmieni. I wciąż wiele pytań jak to zamiast SQL przyłączyć:

Lots of queries, not a join

Jakieś pomysły dlaczego admin Django wydaje się być ignorowanie moich list_select_related i robi kwerend N? Używam Pythona 2.7 i Django 1.3.3.

Odpowiedz

14

Problem polega na tym, że ustawienie dodaje tylko podstawowy select_related() do zapytania, ale to połączenie domyślnie nie jest zgodne z ForeignKeys z null=True. Więc odpowiedź jest zdefiniowanie queryset listy zmian używa się i określ FK do naśladowania:

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

Dzięki! Wartość 'null = True' na kluczu obcym zdecydowanie uniemożliwiła procesowi selected_related robienie tego. Zgaduję, że gdybym podążał za [docs] (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_related) do samego końca, Zauważyłbym, że: "Zauważ, że domyślnie select_related() nie podąża za kluczami obcymi, które mają wartość null = True" –

+0

Ciekawe, czy wiesz dlaczego 'list_select_related = True' nie jest domyślnie dla Django Admin? Wydawałoby się, że jest to rozsądniejsze domyślne. (Rozumiem, dlaczego domyślnie 'select_related()' nie śledzi kluczy obcych, które mają wartość null = True, ponieważ może to być problem z wydajnością, ale zastanawiam się nad 'list_select_related' w innych przypadkach.) –

+0

In Django> = 1.6 metoda nazywa się teraz 'get_queryset'. – TAH

6

Since Django 1.6, list_select_related akceptuje logiczną, listy lub krotki z nazwami pól, aby dołączyć do rozmowy select_related(). Dzięki temu można teraz używać:

class EventAdmin(admin.ModelAdmin): 
    list_display = ('__str__', 'device') 
    list_select_related = ['device'] 
Powiązane problemy