2011-05-11 4 views
12

Django의 ORM을 사용하면 관련 데이터를 기반으로 쿼리 세트에 쉽게 주석을 달 수 있습니다 (필드 추가). 관련 데이터의 여러 필터링 된 하위 세트에 대해 여러 주석을 얻는 방법을 찾지 못했습니다.Django ORM의 데이터 및 복잡한 주석 피벗

오픈 소스 Django-powered trouble-ticket tracker 인 django-helpdesk과 관련된 질문입니다.

CHOICE_LIST = (
    ('open', 'Open'), 
    ('closed', 'Closed'), 
) 

class Queue(models.model): 
    name = models.CharField(max_length=40) 

class Issue(models.Model): 
    subject = models.CharField(max_length=40) 
    queue = models.ForeignKey(Queue) 
    status = models.CharField(max_length=10, choices=CHOICE_LIST) 

그리고이 데이터 집합 :

대기열 :

ID | Name 
---+------------------------------ 
1 | Product Information Requests 
2 | Service Requests 

문제 나는

이 모델을 고려 데이터를 차트 및보고 목적으로이 같은 피벗이 필요합니다 :

ID | Queue | Status 
---+-------+--------- 
1 | 1  | open 
2 | 1  | open 
3 | 1  | closed 
4 | 2  | open 
5 | 2  | closed 
6 | 2  | closed 
7 | 2  | closed 
이 같은 주석/총 모양의 것을보고 싶다 :

Queue ID | Name       | open | closed 
---------+-------------------------------+------+-------- 
1  | Product Information Requests | 2 | 1 
2  | Service Requests    | 1 | 3 

이 엑셀 말투에, 기본적으로 크로스 탭 또는 피벗 테이블입니다. 현재 일부 사용자 지정 SQL 쿼리를 사용하여이 출력을 작성하고 있지만 Django ORM을 사용하여 이동할 수 있으면 WHERE 절을 SQL에 삽입하지 않고도 데이터를보다 쉽게 ​​필터링 할 수 있습니다.

"보너스 포인트"의 경우 : 위의 피벗 필드 (위의 예에서 status)가 날짜 인 경우 어떻게해야하며 월/주/분기/일로 설정해야합니까?

답변

6

당신은 파이썬을 가지고 있습니다.

from collections import defaultdict 
summary = defaultdict(int) 
for issue in Issues.objects.all(): 
    summary[issue.queue, issue.status] += 1 

이제 summary 목적은 두 튜플 키와 큐 상태입니다. 다양한 템플릿 기술을 사용하여 직접 표시 할 수 있습니다.

또는 단순한 경우 테이블과 같은 구조로 다시 그룹화 할 수 있습니다.

table = [] 
queues = list(q for q,_ in summary.keys()) 
for q in sorted(queues): 
    table.append(q.id, q.name, summary.count(q,'open'), summary.count(q.'closed')) 

피벗 테이블을 수행하는 데있어 많은 파이썬 기술이 있습니다.

측정하는 경우 이와 같은 대부분의 Python 솔루션이 실제로 순수한 SQL 솔루션보다 빠르다는 것을 알 수 있습니다. 왜? GROUP-BY의 일부로 정렬을 요구하는 SQL 알고리즘보다 맵핑이 빠를 수 있습니다.

+1

이 표는 크고 거의 일반용으로 간주 할 수없는 경우 무너질 것입니다. – JohnnyM

+0

몇 년 후이 책을 읽은 독자에게 :'collections.defaultdict '객체는'count '와 같은 속성을 갖지 않습니다. python3은 또한'summary.count (q.'closed')' –

2

Django는이 질문에 원래 질문을 받았기 때문에 ORM에 많은 기능을 추가했습니다. Django 1.8 이후로 데이터를 피벗하는 방법에 대한 답은 Case/When conditional expressions을 사용하는 것입니다. 그리고 당신을 위해 그렇게 할 타사 응용 프로그램이 있습니다. PyPIdocumentation