Nobody has started this yet — be first.
Business impact
GET /api/polls/{id}/results/ is the one endpoint whose entire job is to report accurate numbers -- it's what a poll creator screenshots, what gets shown live on a results page, and what any downstream reporting would be built on. Right now total_votes is wrong (it reports how many options the poll has, not how many votes were cast), which cascades into every option's percentage also being wrong -- sometimes reporting over 100% for a single option, which is an immediate, visible sign to any user that the numbers on screen cannot be trusted. For a poll/voting product, "the results are wrong" is about as core a trust failure as there is.
Problem
PollViewSet.results annotates each option with its own vote_count correctly (via Count("votes")), but then computes the poll-wide total_votes as the number of options on the poll instead of the sum of all votes cast across those options.
Current behavior
GET /api/polls/{id}/results/ reports a total_votes equal to the number of options on the poll, not the number of votes actually cast -- which can push individual option percentages above 100%.
Expected behavior
total_votes equals the total number of Vote rows for the poll (the sum of every option's vote_count), and each option's percentage is vote_count / total_votes * 100 against that correct total.
Steps to reproduce
cd django/poll_app source .venv/bin/activate python manage.py runserver &
curl -s -X POST http://127.0.0.1:8000/api/auth/register/ -H "Content-Type: application/json"
-d '{"username":"dave","email":"dave@example.com","password":"d-strong-password-1"}'
curl -s -X POST http://127.0.0.1:8000/api/polls/ -H "Authorization: Token $TOKEN_DAVE" -H "Content-Type: application/json" -d '{"question":"Best editor?","options":["vim","emacs"]}'
Why this matters
This is already covered by two pre-existing tests in polls/tests/test_api.py (test_results_aggregation_counts_and_percentages and test_results_with_zero_votes_does_not_divide_by_zero), both of which currently fail because of it -- the zero-votes test happens to still see 0.0 percentages (0 divided by anything nonzero is still 0), but its total_votes assertion catches the miscount directly.
Suggested approach
Look at how total is computed in PollViewSet.results in polls/views.py, right next to the line that builds options via annotate(vote_count=Count("votes")). Each option in that list already carries its own correct vote_count -- think about what collection total should actually be reducing over.
Acceptance criteria
Verification
.venv/bin/python manage.py test practicetickets.test_ticket03_results_total_votes_miscounted -v 2 && .venv/bin/python manage.py test polls.tests.test_api.PollAPITests.test_results_aggregation_counts_and_percentages polls.tests.test_api.PollAPITests.test_results_with_zero_votes_does_not_divide_by_zero -v 2
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b fix/results-total-votes-miscountedFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/results-total-votes-miscountedSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://127.0.0.1:8000/api/http://127.0.0.1:8000/admin/.env.example.envSECRET_KEYDEBUGDB_*CELERY_BROKER_URLmanage.py testOr via Docker (Postgres, Redis, Django with hot reload, and a Celery worker, all wired together, migrations run automatically on startup):
docker compose up --build
Work the tickets in practicetickets/ (ticket01 through ticket07); each names one dedicated Django test module:
./practicetickets/run_tickets.sh # all 7, clean pass/fail summary
./practicetickets/run_tickets.sh -v # summary + each test's full output
.venv/bin/python manage.py test practicetickets.test_ticket01_permission_check_inverted -v 2 # a single ticket
Three of the seven tickets (01, 02, 03) also collaterally break pre-existing tests in polls/tests/; run .venv/bin/python manage.py test polls -v 2 to confirm the main suite is back to fully green once those are fixed. No Redis or Celery worker is required for any of this -- settings.py forces CELERY_TASK_ALWAYS_EAGER = True whenever "test" appears in sys.argv.
Level 1
Fix a bug
Read existing behaviour, correct it.