Search code examples
djangoorm

Django dividing polls into answered and unanswered


Okay so I have two models 'Question' and 'Answer'. Of course the answer has foreign keys 'user' and 'question'. The list of all the polls worked fine but now Im trying to pass the polls inside two lists: 'answered' and 'unanswered' so I could list the polls in two tables and user could see which polls hes got left.

Basically, I used a simple for loop and it only passes answered questions correctly while it wont pass unanswered questions. I would love to find out why and perhaps how could I approach it differently.

Heres what I did:

def polls_view(request):
    polls = polls.objects.all()
    answers = answers.objects.filter(user=request.user)
    answered = []
    unanswered =[]
    
    for answer in answers:
        if answer.poll in polls:
            answered.append(answer.poll)
    
    for poll in polls:
        if poll not in answered:
            unanswered.append(poll)

Also, adding print(answered) and print(unanswered) displays list of polls type objects in both lists and 'answered' works perfectly in the django template but unanswered isnt there:

{% if not unanswered %}
test
{% endif %}

displays 'test' when rendered.


Solution

  • Assuming the Answer model has a relation with poll, you think on by Polls that has answer as "answered":

    # Annotate each poll with the count of related answers by the current user
    polls = Poll.objects.annotate(num_answers=Count(
    'answer', filter=Q(answer__user=request.user)))
    
    # each poll that has the `num_answer` greater than zero
    answered = polls.filter(num_answer__gt=0)
    
    # and each poll that has the `num_answer` equal zero (unanswered)
    unanswered = polls.filter(num_answer=0)
    

    In this code, we're using Django's annotate() function to add a new 'field' to each poll that is the count of related answers by the current user. Then we filter the polls into two separate querysets: answered contains polls with one or more related answers, and unanswered contains polls with no related answers. It would be good to take a look at Django's aggregation functions: https://docs.djangoproject.com/en/4.2/topics/db/aggregation/

    Some note:

    1. answered and unanswered are querysets and not lists, but you can evaluate it as a list if you want with list(aswered) for example.
    2. Each Poll model object will have an additional num_answers field.
    3. The code above uses answer_set. If you've changed the related name in your foreign key, you will need to adjust it accordingly.