2014-06-22 9 views
5

Ho eseguito l'aggiornamento a Django 1.7, quindi ho potuto ottenere Prefetch objects, ma ho difficoltà a indurli a comportarsi come previsto.Uso di django prefetch_related() per ottenere il tempo dell'ultima attività

Ho un impiegato modello come questo:

class Employee(Human): 
    ... additional Employee Fields ... 

    def get_last_activity_date(self): 
    try: 
     return self.activity_set.all().order_by('-when')[0:1].get().when 
    except Activity.DoesNotExist: 
     return None 

e attività come questo

class Activity(models.Model): 
    when = models.DateTimeField() 
    employee = models.ForeignKey(Employee, related_name='activity_set') 

voglio usare prefetch_related per ottenere l'ultima data di attività per questo dipendente. Ho cercato di esprimere questo molti modi, ma non importa come lo faccio, finisce per generare un'altra query. Le mie altre 2 parti my prefetch_related funzionano come previsto, ma questo non sembra mai salvarmi alcuna domanda.

Io sto usando questo con Django Rest Framework, quindi ho davvero bisogno che la parte prefetch_related funzioni perché non ho modo di raggiungere all'interno del DRF il mapping all'esterno del queryset.

Ecco uno dei modi che non funziona

def get_queryset(self): 

    return super(EmployeeViewSet, self).get_queryset()\ 
      .prefetch_related('phone_number_set', 'email_address_set')\ 
      .prefetch_related(Prefetch('activity_set', Activity.objects.all().order_by('-when')))\ 
      .order_by('last_name', 'first_name') 

noti che sulla query prefetch activity_set che non riesco a tagliare per ottenere solo l'ultima voce di uno che è una preoccupazione in termini di quanta memoria andrà a finire.

In realtà vedo la query di precaricamento che si verifica, ma ogni dipendente riceve una query separata per quella parte di informazioni, il che significa che ho una query sprecata più grande e ancora ottengo i ~ 200 querys che sto cercando di impedire.

Come si ottiene che il prefetch_related funzioni per me in questo caso?

risposta

0

Sospetto che manchi il punto di prefetch_related. I documenti state che questo è il comportamento previsto: molte query e il 'join' in python. Se vuoi meno query dovresti usare select_related Inoltre non sono sicuro che funzionerebbe con i tuoi modelli specifici (non indicati nella domanda) poiché select_related funziona bene con molte o molte relazioni.

UPDATE - la documentazione:

prefetch_related, d'altra parte, fa una ricerca separata per ogni rapporto, e fa il 'entrare' in Python

+1

'selected_related' non funzionerà per questa relazione 'select_related' funziona solo se ForeignKey è nell'Impiegato. Non su una relazione inversa. Quando 'prefetch_related' funziona, si ottiene una query per tutti i dipendenti che quindi estraggono i dati da quella singola query. – boatcoder

+0

Ho il sospetto che i modelli non supporteranno select_related qui. Ma ti sbagli sul significato di prefetch_related. Farebbe molte domande, E 'esplicito nei documenti .. – alonisser

+0

Leggi un po' più vicino, fa una query per relazione, non per modello per relazione. Come ho detto sopra, altri 2 prefetch_related stanno funzionando bene. Questo è diverso in quanto cerca di ottenere il più recente di molti. Sto anche usando DjDT per esaminare le query e sono ciò che mi aspetterei, tutte, tranne la query extra per ogni istanza di modello sull'ultima attività. – boatcoder

Problemi correlati