Pytam o model:
Members.objects.all()
I zwraca:
Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop
Chcę poznać najlepszy sposób Django na uruchomienie group_by
zapytania do mojej bazy danych, na przykład:
Members.objects.all().group_by('designation')
Co oczywiście nie działa. Wiem, że możemy zrobić kilka sztuczek django/db/models/query.py
, ale jestem ciekawy, jak to zrobić bez łatania.
python
django
django-models
po prostu trudne
źródło
źródło
Members.objects.filter(date=some_date).values('designation').annotate(dcount=Count('designation'))
Members.objects.order_by('disignation').values('designation').annotate(dcount=Count('designation'))
Prostym rozwiązaniem, ale nie właściwym sposobem jest użycie surowego SQL :
Innym rozwiązaniem jest użycie
group_by
właściwości:Możesz teraz iterować zmienną wyników, aby pobrać wyniki. Zauważ, że
group_by
nie jest to udokumentowane i może zostać zmienione w przyszłej wersji Django.I ... dlaczego chcesz użyć
group_by
? Jeśli nie używasz agregacji, możesz użyć jejorder_by
do osiągnięcia podobnego wyniku.źródło
Możesz także użyć
regroup
znacznika szablonu do grupowania według atrybutów. Z dokumentów:Wygląda tak:
Działa również na
QuerySet
s wierzę.źródło: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup
edytuj: zwróć uwagę, że
regroup
tag nie działa tak, jak byś tego oczekiwał, jeśli lista słowników nie jest posortowana według klucza. Działa iteracyjnie. Więc posortuj listę (lub zestaw zapytań) według klucza grupującego przed przekazaniem go doregroup
znacznika.źródło
Musisz wykonać niestandardowy kod SQL zgodnie z przykładem w tym fragmencie:
Niestandardowy SQL za pomocą podzapytania
Lub w niestandardowym menedżerze, jak pokazano w internetowych dokumentach Django:
Dodanie dodatkowych metod menedżera
źródło
Django nie obsługuje darmowej grupy według zapytań . Nauczyłem się tego w bardzo zły sposób. ORM nie jest zaprojektowany do obsługi takich rzeczy, jak to, co chcesz robić, bez użycia niestandardowego SQL. Jesteś ograniczony do:
cr.execute
zdania (i ręcznie wykonane parsowanie wyniku)..annotate()
(grupa według zdań wykonywana jest w modelu potomnym dla .annotate (), w przykładach takich jak agregacja lines_count = Count ('lines'))).Za pomocą zestawu zapytań
qs
możesz wywoływać,qs.query.group_by = ['field1', 'field2', ...]
ale ryzykowne jest, jeśli nie wiesz, które zapytanie edytujesz i nie masz gwarancji, że zadziała, a nie uszkodzi wewnętrznych elementów obiektu QuerySet. Poza tym jest to wewnętrzny (nieudokumentowany) interfejs API, do którego nie należy uzyskiwać bezpośredniego dostępu bez ryzyka, że kod nie będzie już zgodny z przyszłymi wersjami Django.źródło
Istnieje moduł, który pozwala grupować modele Django i nadal pracować z zestawem QuerySet w wyniku: https://github.com/kako-nawao/django-group-by
Na przykład:
„book / books.html”
Różnica w stosunku do
annotate
/aggregate
podstawowych zapytań Django polega na użyciu atrybutów powiązanego pola, npbook.author.last_name
.Jeśli potrzebujesz PK instancji, które zostały zgrupowane razem, dodaj następującą adnotację:
UWAGA:
ArrayAgg
jest funkcją specyficzną dla Postgres, dostępną od Django 1.9: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayaggźródło
values
metody. Myślę, że jest w innym celu.values
jest SQL,select
podczas gdygroup_by
jest SQLgroup by
(jak sama nazwa wskazuje ...). Dlaczego głosowanie negatywne? Używamy takiego kodu w produkcji do implementacji złożonychgroup_by
instrukcji.group_by
„zachowuje się głównie jak metoda wartości, ale z jedną różnicą ...” Dokument nie wspomina o SQL,GROUP BY
a podany przypadek użycia nie sugeruje, że ma to coś wspólnego z SQLGROUP BY
. Odwołam głosowanie w dół, gdy ktoś to wyjaśni, ale ten dokument naprawdę wprowadza w błąd.values
, zauważyłem, że przegapiłem, żevalues
samo to działa jak GROUP BY. To moja wina. Myślę, że jest prostszy w użyciuitertools.groupby
niż ten django-group-by, gdyvalues
jest niewystarczający.group by
powyższej czynności za pomocą zwykłegovalues
połączenia - z lubannotate
bez pobierania i bez pobierania wszystkiego z bazy danych. Twoja sugestiaitertools.groupby
działania dla małych zestawów danych, ale nie dla kilku tysięcy zestawów danych, które prawdopodobnie chcesz na stronie. Oczywiście w tym momencie będziesz musiał pomyśleć o specjalnym indeksie wyszukiwania, który i tak zawiera przygotowane (już zgrupowane) dane.Dokument mówi, że można użyć wartości do grupy z queryset.
Możesz znaleźć wszystkie książki i pogrupować je według nazwy, używając tego kodu:
Można pooglądać arkusz cheet tutaj .
źródło
Jeśli się nie mylę, możesz użyć dowolnego zestawu zapytań .group_by = [' field ']
źródło
najpierw musisz zaimportować Suma, a następnie ..
źródło