Skip to content

Feat 144 grouped election endpoints#148

Open
VerrillAng wants to merge 5 commits into
mainfrom
feat_144_grouped-election-endpoints
Open

Feat 144 grouped election endpoints#148
VerrillAng wants to merge 5 commits into
mainfrom
feat_144_grouped-election-endpoints

Conversation

@VerrillAng

Copy link
Copy Markdown

Feature: Grouped Election Endpoints
closes #144

Description:
Adds optional nominees to GET /election and GET /election/{name} via with_nominees=true.
Guests sees:

  1. name
  2. position
  3. speech.

Admins also get:

  1. computing_id
  2. linked_in
  3. instagram
  4. email
  5. discord_username

Features:

  • Added with_nominees query param on list and single election GET endpoints (default false)
  • Integration tests in test_elections.py for guest/admin list and single endpoints (with and without with_nominees), checking response shape and that private fields are hidden from guests

@jbriones1 jbriones1 self-requested a review June 4, 2026 21:36

@jbriones1 jbriones1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR and for writing tests! Lmk if you have any questions about the changes requests.

Comment thread src/elections/urls.py Outdated
Comment thread src/elections/urls.py Outdated
Comment thread src/elections/urls.py Outdated
Comment thread src/elections/urls.py Outdated
Comment thread src/elections/urls.py Outdated
Comment thread src/elections/urls.py Outdated
Comment thread tests/integration/test_elections.py Outdated
Comment thread tests/integration/test_elections.py Outdated
Comment thread tests/integration/test_elections.py Outdated
Comment thread tests/integration/test_elections.py Outdated

@jbriones1 jbriones1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changing things based on my feedback.

The tests look good. If you're not too busy and you're willing to, we can discuss how to populate the database with test data and we could make more comprehensive tests.

Comment thread src/elections/crud.py
NomineeInfoDB.instagram,
NomineeInfoDB.email,
NomineeInfoDB.discord_username,
).join(NomineeInfoDB, CandidateDB.computing_id == NomineeInfoDB.computing_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be outerjoin or else elections without a candidate don't get fetched.

Comment thread src/elections/crud.py
CandidateDB.position,
CandidateDB.speech,
NomineeInfoDB.full_name,
).join(NomineeInfoDB, CandidateDB.computing_id == NomineeInfoDB.computing_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to be outerjoin or else elections without a candidate don't get fetched.

Comment thread src/elections/crud.py
return []
for nomination in all_nominations:
# NOTE: if a nominee does not input their legal name, they are not considered a nominee
nominee_info = await nominees.crud.get_nominee_info(db_session, nomination.computing_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could also be changed so that you can batch all the requests into one DB query instead of having to hit the database for every single nominee, similar to what you did in get_all_nominees_by_election.

Comment thread src/elections/urls.py
db_session: database.DBSession,
with_nominees: bool = Query(False),
):
election_list = await elections.crud.get_all_elections(db_session)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change get_all_nominees_by_election to use (left) outerjoin, then you can change this to election_list = await (elections.crud.get_all_nominees_by_election(...) if has_permission else elections.crud.get_all_elections(...)), and then shuffle the logic around a bit.

Comment thread src/elections/urls.py
if with_nominees:
election_json["candidates"] = await _get_election_nominees(db_session, election, has_permission)
if with_nominees:
nominees = await elections.crud._get_election_nominees(db_session, election, has_permission)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underscore at the front of this function indicates it should only be used internally i.e. not outside of the function's module (file). Its not enforced by the interpreter so this runs fine, but you should remove the underscore so that its clear this is not an internal function.

Comment thread src/nominees/urls.py
dependencies=[Depends(perm_election)],
)
async def delete_nominee_info(db_session: database.tDBSession, computing_id: str):
async def delete_nominee_info(db_session: database.DBSession, computing_id: str):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing that, I let that through >.<

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Grouped election endpoints

2 participants