Nobody has started this yet — be first.
Business impact
The entire point of tracking applications through applied -> interview -> offer/rejected is to be able to answer "what do I need to follow up on right now?" -- which for anyone with more than a handful of applications means filtering to just the ones at a given stage, or just the ones at a specific company. Today there is no way to do that: GET /api/applications/ always returns everything, paginated 20 at a time, and a user with 60 applications has to page through all of them to find the three currently at interview. This directly limits how useful the product is to its heaviest users -- the ones actively job-searching across many companies at once, which is exactly the audience this tool is for.
Problem
ApplicationViewSet.get_queryset() filters only by the requesting user; it never reads self.request.query_params. A request like GET /api/applications/?status=interview is accepted (DRF doesn't reject unknown query params) but silently has no effect -- every application the user owns comes back regardless of status.
Current behavior
GET /api/applications/?status=interview (or ?company=<name>) returns the user's full, unfiltered application list instead of only the matching rows.
Expected behavior
GET /api/applications/?status=<value> returns only applications whose status exactly matches <value>. GET /api/applications/?company=<value> returns only applications whose company contains <value>, case-insensitively. The two filters can be combined (?status=interview&company=acme). Omitting a filter parameter behaves exactly as it does today.
Steps to reproduce
curl -s "http://127.0.0.1:8000/api/applications/?status=interview"
-H "Authorization: Token $TOKEN"
Why this matters
This has to live in get_queryset(), not in the serializer, because it's a "which rows do I return" concern applied before pagination, not a per-object shape concern -- pagination (PAGE_SIZE = 20) has to operate on the already-filtered set, or a user filtering to "interview" would still see unrelated applications mixed into the first page.
Suggested approach
self.request.query_params is where DRF exposes the query string on a ViewSet. You'll conditionally chain additional .filter(...) calls onto the existing owner-scoped queryset based on which of status/company are actually present -- look at how Django's ORM expresses a case-insensitive "contains" lookup for a CharField.
Acceptance criteria
Verification
python manage.py test practicetickets.ticket05_application_filtering -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 feat/application-filteringFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/application-filteringSubmit 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 in.envhttp://127.0.0.1:8000/api/http://127.0.0.1:8000/admin/To run against Postgres via Docker instead:
docker compose up --build # postgres + web, migrations run automatically on startup
Work the tickets in practicetickets/ (TICKET_01 through TICKET_07); each names one dedicated test, addressed by its explicit dotted label since these modules are deliberately named so Django's default test*.py discovery never picks them up:
python manage.py test practicetickets.ticket01_login_credential_swap -v 2 # a single ticket
./practicetickets/run_tickets.sh # all 7, clean pass/fail summary
Two of the seven bugs (tickets 01 and 06) are real enough to also break the project's own pre-existing suite (python manage.py test) -- fixing them correctly makes those pass again too, with zero changes needed inside accounts/tests.py or applications/tests.py.
Level 2
Implement a feature
Extend the system within its own patterns.