Zestawy zapytań Django są leniwe. Oznacza to, że zapytanie trafi do bazy danych tylko wtedy, gdy poprosisz o wynik.
Więc dopóki nie wydrukujesz lub nie użyjesz wyniku zapytania, możesz filtrować dalej bez dostępu do bazy danych.
Jak widać poniżej, kod wykonuje tylko jedno zapytanie SQL, aby pobrać tylko 10 ostatnich elementów.
In[19]:import logging
In[20]: l = logging.getLogger('django.db.backends')In[21]: l.setLevel(logging.DEBUG)In[22]: l.addHandler(logging.StreamHandler())In[23]:User.objects.all().order_by('-id')[:10](0.000) SELECT "auth_user"."id","auth_user"."username","auth_user"."first_name","auth_user"."last_name","auth_user"."email","auth_user"."password","auth_user"."is_staff","auth_user"."is_active","auth_user"."is_superuser","auth_user"."last_login","auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()Out[23]:[<User: hamdi>]
Próbowałem tego na mongoDB i napisano, że SELECT nie jest obsługiwane. Jak to zrobić na mongoDB?
winux
@winux Ponieważ jest to specyficzne dla Django, wygląda na to, że możesz potrzebować skonfigurować Django do pracy z bazami danych typu Mongo / NoSQL. Z mojego doświadczenia nie jest to typowa konfiguracja w odniesieniu do standardowej konfiguracji Django ORM.
anonimowy tchórz
38
Właściwie myślę, LIMIT 10że zostaną wydane do bazy danych, więc krojenie nie nastąpi w Pythonie, ale w bazie danych.
Nadal zastanawiam się, czy limit jest wykonywany w SQL, czy w Pythonie wycina całą tablicę wyników. Nie ma potrzeby pobierania ogromnych list do pamięci aplikacji.
Jako uzupełnienie i spostrzeżenie do innych użytecznych odpowiedzi, warto zauważyć, że faktyczne wykonanie [:10]wycinania zwróci pierwsze 10 elementów listy , a nie ostatnie 10 ...
Aby zdobyć ostatnie 10, powinieneś zrobić [-10:]zamiast tego (patrz tutaj ). Pomoże to uniknąć korzystania order_by('-id')z przy -odwracaniu elementów.
Odpowiedzi:
Zestawy zapytań Django są leniwe. Oznacza to, że zapytanie trafi do bazy danych tylko wtedy, gdy poprosisz o wynik.
Więc dopóki nie wydrukujesz lub nie użyjesz wyniku zapytania, możesz filtrować dalej bez dostępu do bazy danych.
Jak widać poniżej, kod wykonuje tylko jedno zapytanie SQL, aby pobrać tylko 10 ostatnich elementów.
źródło
Właściwie myślę,
LIMIT 10
że zostaną wydane do bazy danych, więc krojenie nie nastąpi w Pythonie, ale w bazie danych.Aby uzyskać więcej informacji, zobacz zestawy zapytań ograniczających .
źródło
Wygląda na to, że rozwiązanie w pytaniu nie działa już w Django 1.7 i pojawia się błąd: „Nie można zmienić kolejności zapytania po pobraniu plastra”
Zgodnie z dokumentacją https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets wymuszając parametr „step” składni plastra Python ocenia zapytanie. Działa w ten sposób:
Nadal zastanawiam się, czy limit jest wykonywany w SQL, czy w Pythonie wycina całą tablicę wyników. Nie ma potrzeby pobierania ogromnych list do pamięci aplikacji.
źródło
Tak. Jeśli chcesz pobrać ograniczony podzbiór obiektów, możesz użyć poniższego kodu:
Przykład:
Początkowe 0 jest opcjonalne, więc
Powyższy kod zwraca pierwsze 10 wystąpień.
źródło
Jako uzupełnienie i spostrzeżenie do innych użytecznych odpowiedzi, warto zauważyć, że faktyczne wykonanie
[:10]
wycinania zwróci pierwsze 10 elementów listy , a nie ostatnie 10 ...Aby zdobyć ostatnie 10, powinieneś zrobić
[-10:]
zamiast tego (patrz tutaj ). Pomoże to uniknąć korzystaniaorder_by('-id')
z przy-
odwracaniu elementów.źródło
Product.objects.filter(~Q(price=0))[-5:]
powoduje ten sam błąd: „Indeksowanie ujemne nie jest obsługiwane”.