2014-04-02 13 views
17

Molto spesso vedo costrutti comeDjango ORM - objects.filter() vs. objects.all(). Filter() - quale è il preferito?

MyModel.objects.all().filter(...) 

, che restituirà un QuerySet del Mananger default. Dapprima all() sembra essere piuttosto ridondante, perché

MyMode.objects.filter(...) 

batte lo stesso risultato.

Tuttavia, questo sembra essere salvo solo il manager di default, a causa dei seguenti due affermazioni nella documentazione Django:

Estratto Fromt il capitolo "Aggiunta di metodi gestore aggiuntivi"

Una consuetudine Il metodo Manager può restituire tutto ciò che vuoi. Non ha per restituire un QuerySet.

Definizione del metodo all() manager:

tutti() Restituisce una copia della QuerySet corrente (o QuerySet sottoclasse). Questo può essere utile in situazioni in cui è possibile passare in un gestore modelli o un QuerySet e filtrare ulteriormente sul risultato . Dopo aver chiamato all() su entrambi gli oggetti, avrai sicuramente un QuerySet con cui lavorare.

Questo mi sembra un po 'come una contraddizione. Django offre da una parte la libertà di consentire a un metodo manager di restituire qualsiasi cosa sia preferibile e dall'altra richiede un QuerySet per il metodo all(). Sono a conoscenza del fatto che ogni manager ha un metodo get_queryset chiamato da all(). Ma chi mi impedisce di ignorare lo all() nel mio gestore personalizzato? Anche se sono d'accordo, sarebbe un cattivo design farlo.

  • Quindi, per quanto posso vedere, il metodo all() non garantisce per restituire un QuerySet. Cosa restituisce esattamente MyModel.objects? Questa affermazione chiama all()? o `get_queryset()?

  • Preferisci MyModel.objects.filter(...) o MyModel.objects.all().filter(...). E se sì, perché?

  • Avete mai incontrato manager sbalorditi che avrebbero combinato con quei metodi in modo indesiderato?

risposta

33

Il metodo all() su un gestore delega a get_queryset(), come si può vedere nella Django source code:

def all(self): 
    return self.get_queryset() 

quindi è solo un modo per ottenere il QuerySet dal Manager. Questo può essere utile per assicurarsi di avere a che fare con un QuerySet e non con un Manager, perché MyModel.objects restituisce un Manager.

Ad esempio, se si desidera iterare tutti gli elementi, è possibile non fare questo:

for item in MyModel.objects: 
    # do something with item 

Poiché non è possibile iterare su un Manager. Tuttavia, all() restituisce il QuerySet, è possibile iterazioni su una QuerySet:

for item in MyModel.objects.all(): 
    # do something with item 

In generale, non si dovrebbe mai sovrascrivere all(). È possibile sovrascrivere get_queryset() ma questo metodo deve restituire un QuerySet.

Se si usa un metodo di filtro come filter() o exclude(), si sarebbe già il QuerySet, because these methods are proxied to the QuerySet. Quindi non devi fare qualcosa come all().filter().

+0

Grazie per me riferimenti di origine. Questo ha spiegato molto. Questo mi ha aiutato a capire molto più le domande di django! –

+0

Hai risposto alla tua domanda? Potresti considerare di accettare questa risposta? http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – rednaw

3
  1. MyModel.objects restituisce l'istanza del gestore. all() restituisce get_query_set(). Penso che tutto sia lì per quando hai bisogno di tutti gli oggetti.
  2. Preferisco MyModel.objects.filter() perché l'altra è solo un'altra chiamata al metodo e non ho bisogno di tutti gli oggetti se filtro :)
  3. Dipende dallo scopo. Ma se sostituiscono un metodo di base del manager, restituiscono lo stesso formato di risultato (es.un QuerySet)
+1

Quindi la risposta è "' 'objects.filter()' 'è preferito, perché scrivendo' 'all()' 'quando in effetti si fa _non_ desidera che tutti gli oggetti non siano pythonic". –

Problemi correlati