2016-07-26 44 views
5

有2個簡單的模型:Django的NotImplementedError:註釋()+不同(場)未實現

class Question(TimeStampedModel): 
    text = models.CharField(max_length=40) 

class Answer(TimeStampedModel): 
    question = models.ForeignKey(Question, related_name='answers') 
    is_agreed = models.BooleanField() 
    author = models.ForeingKey(User, related_name='answers') 

而現在,我將說明我的問題。

In [18]: Question.objects.count() 
Out[18]: 3 

我需要註釋查詢集與 'is_user_agreed' 和 'answers_amount' 字段:

In [18]: user = User.objects.first() 
In [19]: qs = Question.objects.annotate(
    ...:    is_user_agreed=Case(
    ...:     When(answers__in=user.answers.filter(is_agreed=True), then=Value(True)), 
    ...:     When(answers__in=user.answers.filter(is_agreed=False), then=Value(False)), 
    ...:     default=Value(None), 
    ...:     output_field=NullBooleanField(), 
    ...:   ), 
    ...:  ).annotate(answers_amount=Count('answers')) 
    ...: qs.count() 
Out[19]: 4 

^這裏數爲4,但我只有3分貝 :( 做題,我試着distinct()

In [20]: qs.distinct().count() 
Out[20]: 4 # but distinct doesn't work 

In [21]: qs.distinct('id').count() 

和代碼最後一行後,我已經得到了這個異常:

NotImplementedError: annotate() + distinct(fields) is not implemented. 

我也試着用這一招annotate(Count('id')).filter(id__count__gt=1)

但在這種情況下,我失去了所有重複行,並qs.count()爲2

UPDATE:的問題是在queryset中重複行。

SOLUTION:(弗拉基米爾的第二種方法擴展變體)

user = User.objects.first() 
user_agreed_questions = user.answers.filter(
    is_agreed=True).values_list('question_id', flat=True).distinct() 

user_not_agreed_questions = user.answers.filter(
    is_agreed=False).values_list('question_id', flat=True).distinct() 

Question.objects.annotate(
    answer_amount=Count('answers'), 
     is_user_agreed=Case(
      When(id__in=user_agreed_questions, then=True), 
      When(id__in=user_not_agreed_questions, then=False), 
      default=None, 
     output_field=NullBooleanField(), 
    ), 
) 
+0

我不完全確定你要做什麼,但[這個問題可能有幫助](http://stackoverflow.com/questions/13145254/django-annotate-count-with-a-distinct-field )。 – solarissmoke

+0

你在使用postgres嗎? – Sayse

+0

總之,你加入問答表。所以如果第一個問題有兩個答案,第二個問題有一個答案,第三個問題有一個答案,你會得到4(2 + 1 + 1)。你能描述一下queryset的結果嗎?你想得到什麼? –

回答

4

試試這個:

Question.objects.annotate(
    answer_amount=Count('answers'), 
    is_user_agreed=F('answers__is_agreed'), 
).order_by('id', '-answers__is_agreed').distinct('id') 

如果question沒有answers,然後question.is_user_agreedNone。如果question具有至少一個answeranswer.is_agreed=True,則question.is_agreedTrue。否則,is_user_agreedFalse

或者這樣:

agreed_questons = Answer.objects.filter(
    is_agreed=True, 
).values_list('question_id', flat=True).distinct() 

Question.objects.annotate(
    answer_amount=Count('answers'), 
    is_agreed=Case(
     When(id__in=agreed_questions, then=True), 
     When(answers__isnull=True, then=None), 
     default=False, 
     output_field=NullBooleanField(), 
    ), 
) 

agreed_questons是的questionsid名單中,有answer.is_agreed=True至少一個answer

+1

我的註釋效果很好,主要問題是結果quesryset中的重複項。 –

+0

我檢查了你的第二種方法,它適用於我(有問題的細節)。非常感謝! –