2011-06-17 10 views
6

Mam bardzo prosty datamodel z jednego do wielu relacji między filmem i komentarzeJak uniknąć wybrania n + 1 w django?

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

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

Chcę zapytać o filmach i chwycić cały wykres obiektu (wideo ze wszystkimi komentarzami). Patrząc na sql, widzę, że ma dwa wybory, jeden do filmów i jeden do komentarzy. Jak tego uniknąć? Chcę zrobić połączenie i chwycić wszystko na raz.

Czy można to zrobić z django?

Odpowiedz

10

Dla ForeignKey, można użyć selected_related():

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

To wygeneruje tylko jedno zapytanie, zbieranie komentarzu dla ciebie, jak i filmów.

Dla czegoś bardziej złożonego (np. M2M), potrzebna jest zewnętrzna aplikacja, taka jak unjoinify, aby dokonać optymalizacji, ale używa zapytań SQL, aby następnie umieścić je z powrotem w obiektach.

Jeśli jesteś niewygodny z tym (jestem), masz kilka alternatyw:

+0

Chcę zrobić odwrotność, uzyskać komentarze z wideo. Chcę zapytać o filmy, ale otrzymam wszystkie komentarze do tych filmów i otrzymam następującą instrukcję sql: select * from video v join v.id = c.video_id gdzie v.date> some_date. Chodzi o to, aby wszystkie filmy i ich komentarze zostały zebrane w jednym zapytaniu. – bvk

+0

Przepraszam, że moje oświadczenie sql, które zamierzam przedstawić, nie było poprawne. Chcę wygenerować następujące elementy: wybierz * z wideo v lewy dołączyć Komentarz c na v.id = c.id gdzie v.date> some_date. Zasadniczo chcę wszystkie filmy i ich komentarze, nawet filmy bez komentarzy. Ten przykład _Comment.objects.filter (video__title__starts_with = 'The') .select_related ("wideo"). All() _ nie dostanie filmów bez komentarzy. – bvk

+0

Dlatego dałem ci link do innych narzędzi, takich jak django-batch-select, które mogą zrobić to dla ciebie: "roughtly select_related, który działa z M2M i REVERSE RELATIONS". –

1

Co musisz zrobić, to użyć opcji select_related w komentarzu.

Powiedzmy, że trzeba znaleźć wszystkie filmy, których tytuł zaczyna się od „W” i uwag związanych z nim

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

To załadować wszystkie komentarze i odpowiedni obiekt Video dla tego komentarza. Będziesz musiał przestawić się na wideo, aby powtórzyć filmy. Użyj funkcji python itertools.groupby, aby wykonać obroty w pamięci.

Powiązane problemy