2015-09-10 24 views
5

Wiem, że regularne zapytania lub metody kwerend iteracji oceniają i zwracają cały zestaw danych w jednym ujęciu.Pobieranie danych zestawów kwerend pojedynczo

na przykład wziąć to:

my_objects = MyObject.objects.all() 
for rows in my_objects:   # Way 1 
for rows in my_objects.iterator(): # Way 2 

Pytanie

w obu metodach wszystkie wiersze są pobierane w ciągu single-go.Is jakiś sposób w djago że wiersze mogą być queryset pobierane jeden po drugim z bazy danych.

Dlaczego ten dziwny wymóg

Obecnie moja kwerenda pobiera pozwala mówi n wierszy, ale kiedyś dostanę Python and Django OperationalError (2006, 'MySQL server has gone away').

więc mieć obejście tego, Obecnie używam dziwne while zapętlenie logic.So zastanawiałem się, czy istnieje jakikolwiek rodzimy lub wbudowana metoda jest moje pytanie czy nawet logiczne na pierwszym miejscu !! :)

Odpowiedz

2

Myślę, że szukasz limit your query set.

Cytat powyższy link:

Użyj podzbiór składni array-krojenie Pythona ograniczyć QuerySet do pewnej liczby wyników. Jest to odpowiednik klauzul LIMIT i OFFSET języka SQL.

Innymi słowy, jeśli zaczynają się liczyć można następnie pętli nad i wziąć plastry, jak wymaga od nich ..

cnt = MyObject.objects.count() 
start_point = 0 
inc = 5 
while start_point + inc < cnt: 
    filtered = MyObject.objects.all()[start_point:inc] 
    start_point += inc 

oczywiście konieczne może obsłużyć tego błędu więcej ..

+0

Ja zakładając masz spojrzał na ustalenie rzeczywistego problemu tutaj, że byłoby oczywiście korzystne :) – Sayse

+0

jest to z pewnością jeden sposób mam uwzględnione podczas kopania wokół, wygląda neat.I am zastanawiasz się, czy istnieje inny * rodzimy * sposób w samym Django bez ograniczeń? Jeśli chodzi o Rzeczywisty problem, to jest on związany z wersją django, ale ponieważ cały projekt jest na nim oparty, nie mogę nic z tym zrobić ... – NoobEditor

+0

@NoobEditor - Wydaje mi się, że dotyczy to tak natywnego, jak to tylko możliwe, ponieważ zmodyfikuje to zapytanie, które wykonujesz. Nadal będziesz wykonywać wiele zapytań na db, ale tylko zwracając N wyników naraz. Inną opcją jest sprawdzenie, co faktycznie powinieneś zwrócić i użycie "wartości" do zwrócenia tych pól. (Zwróć też uwagę, że podczas mojego przykładu oglądam tylko 5 w tym samym czasie, wyobrażam sobie, że możesz obsłużyć o wiele więcej niż to jednocześnie) – Sayse

2

Pobieranie kolejnych wierszy może być gorsze. Możesz chcieć odzyskać partie dla 1000s itp. Mam used this django snippet (nie moją pracę) z powodzeniem z bardzo dużymi zapytaniami. Nie zżera pamięci i nie ma problemu z oderwaniem połączenia.

Oto urywek z tego linku:

import gc 

def queryset_iterator(queryset, chunksize=1000): 
    ''''' 
    Iterate over a Django Queryset ordered by the primary key 

    This method loads a maximum of chunksize (default: 1000) rows in it's 
    memory at the same time while django normally would load all rows in it's 
    memory. Using the iterator() method only causes it to not preload all the 
    classes. 

    Note that the implementation of the iterator does not support ordered query sets. 
    ''' 
    pk = 0 
    last_pk = queryset.order_by('-pk')[0].pk 
    queryset = queryset.order_by('pk') 
    while pk < last_pk: 
     for row in queryset.filter(pk__gt=pk)[:chunksize]: 
      pk = row.pk 
      yield row 
     gc.collect() 
+0

Twój URL nie otwiera mate! – NoobEditor

+0

@ e4c5: przekierowanie na http: //https//djangosnippets.org/snippets/1949/ .. ale nie pokazuje żadnej strony .. ponownie sprawdź fella !! : D – NoobEditor

+0

Odpowiedź zaktualizuj, kopiując i wklejając fragment. – e4c5

1

Aby rozwiązać (2006, „serwer MySQL zniknęło”) problemu, twoje podejście nie jest logiczne. Jeśli trafisz w bazę danych dla każdego wpisu, zwiększy to liczbę zapytań, co samo w przyszłości spowoduje problem, ponieważ rośnie wykorzystanie aplikacji. Myślę, że powinieneś zamknąć połączenie mysql po wykonaniu iteracji wszystkich elementów wyniku, a jeśli spróbujesz wykonać inne zapytanie, django utworzy nowe połączenie.

from django.db import connection: 
connection.close() 

Refer this for more details

+0

Problem polega na tym, że 'połaczenie' jest wyrzucane podczas pobierania zestawu zapytań ... stąd błąd. Nawet jeśli zamknę i uruchomię i nowe połączenie, napotykam ponownie ten sam problem.Spróbowałem' connections.connection' & 'is_usable', ale bez pomocy! : \ – NoobEditor

Powiązane problemy