2011-09-15 4 views
0

Avoir le modèle:vues Django - requête optimale située dans un modèle de ForeignKey

class Notebook(models.Model): 
    n_id = models.AutoField(primary_key = True) 

class Note(models.Model): 
    b_nbook = models.ForeignKey(Notebook) 

le format d'URL passant un paramètre:

(r'^(?P<n_id>\d+)/$', 'notebook_notes') 

et la vue suivante:

def notebook_notes(request, n_id): 
    nbook = get_object_or_404(Nbook, pk=n_id) 
... 

lequel des énoncés suivants est l'ensemble de requêtes optimal, et pourquoi? (Ils travaillent tous les deux et passent les notes basées sur un bloc-notes sélectionné par URL)

notes = nbook.note_set.filter(b_nbook = n_id) 
notes = Note.objects.select_related().filter(b_nbook = n_id) 

Répondre

1

Eh bien, vous vous comparez des pommes et des oranges un peu là-bas. Ils peuvent revenir pratiquement les mêmes, mais vous faites des choses différentes sur les deux.

Prenons d'abord la version relationnelle. Cette requête dit obtenir toutes les notes qui appartiennent à nbook. Vous filtrez ensuite ce jeu de requête uniquement par des notes appartenant à nbook. Vous le filtrez deux fois sur les mêmes critères, en effet. Puisque les querysets de Django sont paresseux, cela ne fait vraiment rien de mal, comme frapper la base de données plusieurs fois, mais c'est toujours inutile.

Maintenant, la deuxième version. Ici, vous commencez avec toutes les notes et le filtrage à ceux qui appartiennent à l'ordinateur portable particulier. Il n'y a qu'un seul filtre cette fois, mais c'est une mauvaise forme de le faire de cette façon. Comme il s'agit d'une relation, vous devez rechercher le format relationnel, c'est-à-dire nbook.note_set.all(). Sur cette version, cependant, vous utilisez également select_related(), qui n'a pas été utilisé sur l'autre version.

select_related va tenter de créer une table de jointure avec d'autres relations sur le modèle, dans ce cas un Note. Cependant, puisque la seule relation sur Note est Notebook et que vous avez déjà le portable, c'est redondant.

Prendre toutes les redondances dans les deux versions vous laisse avec juste:

notes = nbook.note_set.all() 

Cela aussi, retournera exactement les mêmes résultats que les deux autres versions, mais est beaucoup plus propre et standardisée.

+0

Merci pour la réponse détaillée! Cela fonctionne bien et c'est le meilleur moyen pour cette affaire. – barbarosa