2009-07-21 4 views
1

Django ORM의 새로운 집계 기능을 사용하고 있는데 문제가 있습니다. 이 가능해야한다고 생각합니다.하지만 얻을 수없는 것 같습니다. 그것은 작동합니다. 생성하려고하는 쿼리 유형은 here입니다.Django - 각 그룹의 극단적 인 회원 찾기

자, 나는 다음과 같은 모델이 있다고 가정 해 보자 - 그래서

class ContactGroup(models.Model): 
    .... whatever .... 

class Contact(models.Model): 
    group = models.ForeignKey(ContactGroup) 
    name = models.CharField(max_length=20) 
    email = models.EmailField() 
... 

class Record(models.Model): 
    contact = models.ForeignKey(Contact) 
    group = models.ForeignKey(ContactGroup) 
    record_date = models.DateTimeField(default=datetime.datetime.now) 

    ... name, email, and other fields that are in Contact ... 

, 해당 시간의 접촉에 표시되는 정보를 저장하는 연락이 새로운 기록이 생성됩니다 생성되거나 수정 될 때마다 타임 스탬프와 함께 이제는 ContactGroup과 연결된 모든 Contact에 대해 가장 최근의 Record 인스턴스를 반환하는 쿼리를 원합니다. 의사 코드에서 :이 알아 낸 일단

group = ContactGroup.objects.get(...) 
records_i_want = group.record_set.most_recent_record_for_every_contact() 

, 난 그냥 검색어 세트에 filter(record_date__lt=some_date)을 던져, 그리고 그것을 some_date에 존재했던 정보를 얻을 수 있어야합니다.

아무도 아이디어가 있습니까?

편집 : 나 자신을 분명히하고있는 것은 아닙니다.

ContactGroup.record_set.extra(where=["history_date = (select max(history_date) from app_record r where r.id=app_record.id and r.history_date <= '2009-07-18')"]) 

이 WHERE 절에 하위 쿼리를 두는 것은이 문제를 해결하기위한 하나 개의 전략이다, 다른 사람은 :이 같은 모델을 사용하여, 나는이 방법은 (여분의()) 순수 장고 ORM으로 다음하지 싶지 위의 첫 번째 링크에서 꽤 잘 설명됩니다. extra()를 사용하지 않고 where-clause subselect를 사용할 수 없다는 것을 알고 있지만 아마도 다른 집계 방법 중 하나가 새로운 집계 기능에 의해 가능해질 것이라고 생각했습니다.

+0

왜 레코드 및 연락처 모델 모두에서 ContactGroup에 외래 키가 있습니까? 또한 사소한 단점이 있지만, 명시 적으로 기본값을 지정하는 대신 DateTimeField에서 auto_now 또는 auto_now_add를 사용하는 것이 일반적으로 더 편리합니다. – oggy

+0

Record의 외래 키가 있습니다. Contact의 정확한 사본과 접촉 할 외래 키와 record_date이기 때문입니다. 특정 시간에 연락 상대의 스냅 샷입니다. 또한 auto \ _now 및 auto \ _now \ _add는 진단하기 힘든 버그를 유발하고 핵심 커미터가 싫어하며 datetime.datetime보다 편리하지 않습니다. –

답변

0

장고에서 개체에 대한 변경 기록을 남기고 싶은 것 같습니다.

Pro Django에는 삽입/삭제/업데이트를 위해 추적하는 클라이언트로 다른 모델을 사용하는 모델을 만드는 방법을 보여주는 11 장 (확장 응용 프로그램)의 섹션이 있습니다.이 모델은 클라이언트에서 동적으로 생성됩니다 정의에 의존하고 신호에 의존합니다. 이 코드는 most_recent() 함수를 보여 주지만이를 적용하여 특정 날짜에 객체 상태를 얻을 수 있습니다.

장고에서 문제가되는 트래킹이라고 가정합니다. 이걸 얻기위한 SQL이 아닌가요? 모든

+0

실제로 저는 HistoricalRecords Pro Django의 app을 사용하여 기록을 추적하십시오. 간단하게 유지하기 위해 언급하지 않았습니다. 이 응용 프로그램을 사용하면 단일 객체 인스턴스를 요구하지만 객체 세트는 요구하지 않습니다. –

0

첫째, 지적거야 그 :

ContactGroup.record_set.extra(where=["history_date = (select max(history_date) from app_record r where r.id=app_record.id and r.history_date <= '2009-07-18')"]) 

당신에게 같은 효과를 얻을 수 없습니다 :

records_i_want = group.record_set.most_recent_record_for_every_contact() 

가 첫 번째 쿼리는 특정 그룹과 관련된 모든 레코드를 반환 (또는 특정 그룹의 연락처 중 하나와 연결되어 있음)에 추가로 지정된 날짜/시간보다 작은 record_date를가집니다. 쉘에서이 프로그램을 실행 한 다음이 쿼리가 생성 장고 검토 않습니다

from django.db import connection 
connection.queries[-1] 

알 수있는 :

'SELECT "contacts_record"."id", "contacts_record"."contact_id", "contacts_record"."group_id", "contacts_record"."record_date", "contacts_record"."name", "contacts_record"."email" FROM "contacts_record" WHERE "contacts_record"."group_id" = 1 AND record_date = (select max(record_date) from contacts_record r where r.id=contacts_record.id and r.record_date <= \'2009-07-18\') 

아니 정확히 당신이 원하는, 맞죠?

이제 집계 기능은 집계 된 데이터와 관련된 개체가 아닌 집계 된 데이터를 검색하는 데 사용됩니다. 따라서 group.record_set.most_recent_record_for_every_contact()을 얻으려고 할 때 집계를 사용하여 실행 된 쿼리의 수를 최소화하려는 경우 성공하지 못합니다. 집계를 사용하지 않고

, 당신은 사용하여 그룹과 관련된 모든 연락처에 대한 가장 최근의 기록을 얻을 수 있습니다 :

[x.record_set.all().order_by('-record_date')[0] for x in group.contact_set.all()] 

집계를 사용하여, 나는 그에게 얻을 수있는 가장 가까운이었다 :

group.record_set.values('contact').annotate(latest_date=Max('record_date')) 

후자는 다음과 같은 사전 목록을 반환합니다.

[{'contact': 1, 'latest_date': somedate }, {'contact': 2, 'latest_date': somedate }] 

주어진 그룹의 각 연락처와 그 그룹과 관련된 최신 기록 날짜.

어쨌든 최소 검색어 수는 아마도 그룹의 1 + 연락처 수입니다. 단일 쿼리를 사용하여 결과를 얻고 싶다면 그 방법도 가능하지만 다른 방법으로 모델을 구성해야합니다. 그러나 그것은 당신의 문제와 완전히 다른 측면입니다.

이것이 합계/일반 ORM 기능을 사용하여 문제에 접근하는 방법을 이해하는 데 도움이되기를 바랍니다.

관련 문제