2011-06-17 27 views
6

que tienen un modelo de datos muy simple con una relación de uno a muchos entre el vídeo y comentaCómo evitar n + 1 seleccionar en django?

class Video(models.Model): 
    url = models.URLField(unique=True) 
    ..... 

class Comment(models.Model): 
    title = models.CharField(max_length=128) 
    video = models.ForeignKey('Video') 
     ..... 

Quiero consultar los vídeos y apoderarse de todo el gráfico de objetos (un video con todas las observaciones). Al mirar el sql, veo que tiene dos selecciones, una para los videos y otra para los comentarios. ¿Cómo evito eso? Quiero hacer una unión y agarrar todo de una vez.

¿Es posible hacer esto con django?

Respuesta

10

Para ForeignKey, puede utilizar selected_related():

Comment.objects.select_related('video').all() 

Se generará sólo una consulta, la recopilación de comentarios para usted, así como videos.

Para algo más complejo (como M2M), necesita una aplicación externa como unjoinify para realizar optimizaciones pero utiliza consultas SQL para luego volver a colocarlas en los objetos.

Si usted es incómodo con esto (soy), que tienen algunas alternativas:

+0

Quiero hacer lo contrario, obtener los comentarios del video. Deseo consultar videos pero obtener todos los comentarios para esos videos y dar como resultado un enunciado SQL como ese: seleccione * del video v join v.id = c.video_id donde v.date> some_date. La idea es obtener todos los videos y sus comentarios en una consulta. – bvk

+0

Lo siento, mi afirmación de SQL que estoy buscando producir no era correcta. Deseo generar lo siguiente: seleccionar * de Videos v left join Comentario c en v.id = c.id donde v.date> some_date. Esencialmente quiero todos los videos y sus comentarios, incluso los videos sin comentarios. Este ejemplo _Comment.objects.filter (video__title__starts_with = 'The') .select_related ('video'). All() _ no obtendrá los videos sin comentarios. – bvk

+0

Es por eso que le di un enlace a otras herramientas, como django-batch-select, que pueden hacer esto por usted: "realmente es un select_related que funciona con M2M y REVERSE RELATIONS". –

1

Lo que debe hacer es utilizar el elemento select_related en el comentario.

digamos que usted necesita para encontrar el todos los vídeos cuyo título comienza con 'El' y los comentarios relacionados con ella

comments = Comment.objects.filter(video__title__starts_with='The') 
      .select_related('video').all() 

Esto cargará todos los comentarios y el objeto de vídeo apropiado para ese comentario. Aún deberá pivotar sobre el Video para iterar sobre los videos. Use la función python itertools.groupby para hacer eso pivotando en la memoria.

Cuestiones relacionadas