모델을 쿼리합니다.
Members.objects.all()
그리고 그것은 반환합니다 :
Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop
내가 원하는 것은 group_by
다음과 같이 데이터베이스에 쿼리를 실행 하는 가장 좋은 Django 방법을 아는 것입니다.
Members.objects.all().group_by('designation')
물론 작동하지 않습니다. 나는 우리가 몇 가지 트릭을 할 수 있다는 것을 알고 django/db/models/query.py
있지만 패치하지 않고 어떻게 해야하는지 궁금합니다.
답변
집계를 수행 하려는 경우 ORM 의 집계 기능을 사용할 수 있습니다 .
from django.db.models import Count
Members.objects.values('designation').annotate(dcount=Count('designation'))
이로 인해 유사한 쿼리가 생성됩니다
SELECT designation, COUNT(designation) AS dcount
FROM members GROUP BY designation
출력 형태는
[{'designation': 'Salesman', 'dcount': 2},
{'designation': 'Manager', 'dcount': 2}]
답변
쉬운 해결책이지만 올바른 방법은 아닙니다. raw SQL 을 사용하는 것입니다 .
results = Members.objects.raw('SELECT * FROM myapp_members GROUP BY designation')
또 다른 해결책은 group_by
속성 을 사용하는 것입니다 .
query = Members.objects.all().query
query.group_by = ['designation']
results = QuerySet(query=query, model=Members)
이제 결과 변수를 반복하여 결과를 검색 할 수 있습니다. 참고group_by
문서화되지 않고 장고의 향후 버전에서 변경 될 수 있습니다.
그리고 … 왜 사용하고 싶 group_by
습니까? 집계를 사용하지 않으면 order_by
같은 결과를 얻을 수 있습니다.
답변
regroup
템플릿 태그를 사용하여 속성별로 그룹화 할 수도 있습니다 . 문서에서 :
cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]
...
{% regroup cities by country as country_list %}
<ul>
{% for country in country_list %}
<li>{{ country.grouper }}
<ul>
{% for city in country.list %}
<li>{{ city.name }}: {{ city.population }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
다음과 같습니다 :
- 인도
- 뭄바이 : 19,000,000
- 캘커타 : 15,000,000
- 미국
- 뉴욕 : 20,000,000
- 시카고 : 7,000,000
- 일본
- 도쿄 : 33,000,000
그것은 또한 QuerySet
내가 믿는 것에서 작동합니다 .
출처 : https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup
편집 : 사전 목록이 키 정렬되어 있지 않으면 예상대로 regroup
태그 가 작동 하지 않습니다 . 반복적으로 작동합니다. 따라서 그룹화 키로 목록 (또는 쿼리 세트)을 정렬 한 다음 regroup
태그로 전달하십시오 .
답변
이 스 니펫에 예시 된대로 사용자 지정 SQL을 수행해야합니다.
또는 온라인 Django 문서에 표시된 사용자 지정 관리자에서
답변
Django는 무료 그룹 별 쿼리를 지원하지 않습니다 . 나는 그것을 아주 나쁜 방법으로 배웠다. ORM은 사용자 지정 SQL을 사용하지 않고 원하는 작업을 지원하도록 설계되지 않았습니다. 귀하는 다음으로 제한됩니다 :
- RAW SQL (예 : MyModel.objects.raw ())
cr.execute
문장 (및 결과의 손으로 만든 파싱)..annotate()
(문별 그룹화는 .annotate ()의 하위 모델에서 행 _ 집계 = 횟수 ( ‘lines’) 집계와 같은 예에서 수행됨).
쿼리 세트를 통해 qs
호출 할 수는 qs.query.group_by = ['field1', 'field2', ...]
있지만 편집중인 쿼리를 모르고 쿼리 세트 개체의 내부를 손상시키지 않을 것이라는 보장이없는 경우 위험합니다. 또한 내부 (문서화되지 않은) API이므로 코드가 향후 장고 버전과 더 이상 호환되지 않을 위험없이 직접 액세스해서는 안됩니다.
답변
Django 모델을 그룹화하고 여전히 결과에서 QuerySet으로 작업 할 수있는 모듈이 있습니다 : https://github.com/kako-nawao/django-group-by
예를 들면 다음과 같습니다.
from django_group_by import GroupByMixin
class BookQuerySet(QuerySet, GroupByMixin):
pass
class Book(Model):
title = TextField(...)
author = ForeignKey(User, ...)
shop = ForeignKey(Shop, ...)
price = DecimalField(...)
class GroupedBookListView(PaginationMixin, ListView):
template_name = 'book/books.html'
model = Book
paginate_by = 100
def get_queryset(self):
return Book.objects.group_by('title', 'author').annotate(
shop_count=Count('shop'), price_avg=Avg('price')).order_by(
'name', 'author').distinct()
def get_context_data(self, **kwargs):
return super().get_context_data(total_count=self.get_queryset().count(), **kwargs)
‘book / books.html’
<ul>
{% for book in object_list %}
<li>
<h2>{{ book.title }}</td>
<p>{{ book.author.last_name }}, {{ book.author.first_name }}</p>
<p>{{ book.shop_count }}</p>
<p>{{ book.price_avg }}</p>
</li>
{% endfor %}
</ul>
annotate
/ aggregate
기본 Django 쿼리 와의 차이점 은 관련 필드의 속성을 사용한다는 것입니다 book.author.last_name
.
함께 그룹화 된 인스턴스의 PK가 필요한 경우 다음 주석을 추가하십시오.
.annotate(pks=ArrayAgg('id'))
참고 : ArrayAgg
Django 1.9 이상에서 사용할 수있는 Postgres 관련 기능입니다. https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayagg
답변
이 문서 에서는 값을 사용하여 쿼리 집합을 그룹화 할 수 있다고 말합니다.
class Travel(models.Model):
interest = models.ForeignKey(Interest)
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True)
# Find the travel and group by the interest:
>>> Travel.objects.values('interest').annotate(Count('user'))
<QuerySet [{'interest': 5, 'user__count': 2}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited for 2 times,
# and the interest(id=6) had only been visited for 1 time.
>>> Travel.objects.values('interest').annotate(Count('user', distinct=True))
<QuerySet [{'interest': 5, 'user__count': 1}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited by only one person (but this person had
# visited the interest for 2 times
이 코드를 사용하여 모든 책을 찾아 이름별로 그룹화 할 수 있습니다.
Book.objects.values('name').annotate(Count('id')).order_by() # ensure you add the order_by()
여기 치트 시트를 볼 수 있습니다 .