2014-08-31 2 views
4

저는 장고 1.7을 사용 중이며 ORM의 새로운 기능의 장점을 찾으려고합니다.Django 1.7과 똑똑하고 깊고 필터링 된 집계

class Player(models.Model): 
    name = models.CharField(...) 

class Question(models.Model): 
    title = models.CharField(...) 
    answer1 = models.CharField(...) 
    answer2 = models.CharField(...) 
    answer3 = models.CharField(...) 
    right = models.PositiveSmallIntegerField(...) #choices=1, 2, or 3 

class Session(models.Model): 
    player = models.ForeignKey(Player, related_name="games") 

class RightAnswerManager(models.Manager): 

    def get_queryset(self): 
     super(RightAnswerManager, self).get_queryset().filter(answer=models.F('question__right')) 

class AnsweredQuestion(models.Model): 
    session = models.ForeignKey(Session, related_name="questions") 
    question models.ForeignKey(Question, ...) 
    answer = models.PositiveSmallIntegerField(...) #1, 2, 3, or None if not yet ans. 

    objects = models.Manager() 
    right = RightAnswerManager() 

나는 내가 할 수있는 알고 :

Session.objects.prefetch_related('questions') 

을 그리고 질문 세션을 얻을

내가 가진 가정합니다.

Session.objects.prefetch_related(models.Prefetch('questions', queryset=AnsweredQuestion.right.all(), to_attr='answered')) 

을 그리고 실제로 응답 오른쪽 한 질문 목록과 세션을 얻을 :

또한, 저는 할 수 있습니다.

하지만 내가 대신 요소의 수를 -eg- 얻기 위해, 그 동안 집계를 수행 할 수 없습니다

FieldError: Cannot resolve keyword 'rightones' into field. Choices are: id, name, sessions 

이가 아니라 : answered 이후

Session.objects.prefetch_related(models.Prefetch('questions', queryset=AnsweredQuestion.right.all(), to_attr='answered')).annotate(total_right=models.Count('answered')) 

실제 필드 아니다 샘플을 포함하고 있지 않은 모델이 많기 때문에 샘플을 제공합니다. 그러나 그 아이디어는 분명합니다. 나는 생성 된 속성을 모을 수 없습니다.

방법은 있습니까 원시에 떨어지지 않고 다음 질문에 대답하십시오?

Get each user annotated with their "points". 
A user may play any amount of sessions. 
In each session it gets many questions to answer. 
For each right answer, a point is earned. 

RAW SQL에서는이 될 것 같은 : 그룹화 필드에 함수 적 종속성이 이후, 나는 사용자 데이터를 수집하고 관련 answeredquestions을 계산 것 같은

SELECT user.*, COUNT(answeredquestion.id) 
FROM user 
LEFT OUTER JOIN session ON (session.user_id = user.id) 
INNER JOIN answeredquestion ON (answeredquestion.session_id = session.id) 
INNER JOIN question ON (answeredquestion.question_id = question.id) 
WHERE answeredquestion.answer = question.right 
GROUP BY user.id 

또는 뭔가 (, 조건이 통과한다고 가정). 따라서 원시 검색어는 나를위한 옵션이 아닙니다.

아이디어는 총점을 가진 사용자를 얻는 것입니다.

내 질문에 두 가지 방법 중 하나로 응답 할 수 있습니다.

  • 같은 쿼리를 수행 할 수있는 방법이 있나요 (실제로 나는이 정확한 쿼리를 테스트하지, 그것은 아이디어를 제시 여기) 장고 1.7에서 ORM으로, 어떻게 든 관련/역 FK의 프리 페치 또는 관리자의 선택을 제공 전지? 반복은 허용되지 않습니다. (N + 1 문제의 2 차 버전을 사용하고 있습니다!).
  • 어떻게 든 이것을하는 장고 패키지가 있습니까? 아마도 제 3 자에 의해 제공되는 RAW 호출의 추상화를 수행합니다. 이것은 많은 쿼리가 있기 때문에입니다..

답변

0

프리 페치를 사용하면이 상황에서 어떤 이득도 얻지 못한다고 생각합니다. 일반적으로 prefetch_related 및 select_related는 필터 세트를 반복하고 각 객체에 대한 관련 객체에 액세스 할 때 사용됩니다. 초기 쿼리에서 annotate를 수행함으로써 django가 최적화를 수행 할 것이라고 믿습니다.

Player.objects.annotate(total_right=models.Count('games__questions__right')) 
: 질문에 대한

점 "각 사용자가 자신의 주석하기" "이 쿼리를 시도