Conversation
use Q objects so nominations without a pre-created expiry round are not silently excluded from active views by the FK join filter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nominations_cutoff date (e.g. feb 20) is now the last day nominations are accepted, matching the wg charter intent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…gnal queryset.update() bypassed the post_save cdn purge signal and skipped setting auto_now fields. iterating with save() ensures cache invalidation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
the vote view is a createview with no update path; the old text implied votes could be changed after casting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
<center> is obsolete in html5; use text-align: center instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
form-level check in clean_nominee_email rejects submissions when a nomination already exists for that email in the current open round. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prevents breaking the slug and fk relationships by changing year/quarter on existing rounds. uses disabled=true for tamper safety. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
adds is_superuser check to match the access logic already used in FellowNominationDetail.get_object for consistency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
previously the nomination form rendered after the cutoff date but form_valid rejected the POST, giving users a confusing 404 on submit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prevents wg members from voting on pending, accepted, or not_accepted nominations which defeats the review workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
self.get_queryset().count() fired a redundant query; context["fellows"] already holds the same queryset from the parent get_context_data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace relative dot imports with absolute `nominations.tests.factories` imports. Migrate test assertions from Membership to Fellow model. Fix nomination_statement min-length in test data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| nomination_round=current_round, | ||
| ).exists(): | ||
| raise forms.ValidationError( | ||
| "This person has already been nominated for the current round." |
There was a problem hiding this comment.
do we want to provide this information publicly or maybe just say "cool thanks for your submission" and silently discard.
or perhaps a bigger question, should multiple nominations be additive. it would maybe speak highly of the person being nominated if, say, 5 people nominated with extnesive statements vs just 1 and the rest not being taken into account? a question for the WG
| # 'example-task': { | ||
| # 'task': 'users.tasks.example_task', | ||
| # }, | ||
| 'close-expired-fellow-nominations': { |
| def _get_site_url(request=None): | ||
| """Build the site base URL from the request or the Sites framework.""" | ||
| if request: | ||
| scheme = "https" if request.is_secure() else "http" | ||
| return f"{scheme}://{request.get_host()}" | ||
| try: | ||
| site = Site.objects.get_current() | ||
| domain = site.domain | ||
| scheme = "http" if "localhost" in domain or "127.0.0.1" in domain else "https" | ||
| return f"{scheme}://{domain}" | ||
| except Exception: | ||
| return "https://www.python.org" |
There was a problem hiding this comment.
this does not belong here
| {% block left_sidebar %}{% endblock %} | ||
| {% block content_attributes %}{% endblock %} | ||
|
|
||
| {% block head %} |
There was a problem hiding this comment.
Pull request overview
This PR introduces a comprehensive Fellow nominations system for the Python Software Foundation, enabling the PSF Fellow Work Group to manage quarterly nomination rounds, review nominations, vote on candidates, and maintain a public roster of all PSF Fellows.
Changes:
- Implements a complete Fellow nominations workflow with models for nominations, nomination rounds, votes, and Fellows
- Adds 12 new HTML templates for public roster, nomination submission, WG dashboard, review interface, and admin management
- Includes comprehensive email notification system for nominators and WG members
- Provides extensive test coverage across models, views, forms, and management commands
Reviewed changes
Copilot reviewed 47 out of 51 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
| nominations/models.py | Adds Fellow, FellowNomination, FellowNominationRound, and FellowNominationVote models with business logic |
| nominations/views.py | Implements 15+ views for public roster, nomination creation, WG dashboard, review, voting, and round management |
| nominations/forms.py | Defines forms for nomination submission, round management, voting, and status updates with validation |
| nominations/urls.py | Registers URL patterns for all Fellow nomination views |
| nominations/admin.py | Configures Django admin interfaces for Fellow-related models |
| nominations/notifications.py | Email notification system for submission confirmations and status updates |
| nominations/managers.py | Custom QuerySet manager for filtering active nominations |
| nominations/tasks.py | Celery task for automated expiry of old nominations |
| templates/nominations/*.html | 12 templates for public and WG-restricted interfaces |
| templates/nominations/email/*.{txt,html} | Plain text and HTML email templates for notifications |
| nominations/tests/*.py | Comprehensive test suite covering models, views, forms, and management commands |
| nominations/migrations/*.py | Database migrations for new models |
| nominations/management/commands/*.py | Management commands for test data creation and expired nomination cleanup |
| pydotorg/urls.py | Registers public Fellows roster URLs |
| pydotorg/settings/base.py | Adds Celery scheduled task and WG notification email setting |
| pydotorg/settings/local.py | Configures SMTP email backend for local development |
| docker-compose.yml | Adds maildev service for local email testing |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 47 out of 51 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
nominations/management/commands/close_expired_fellow_nominations.py
Outdated
Show resolved
Hide resolved
Replaces manual Q1-Q4 constants and QUARTER_CHOICES tuple with a models.IntegerChoices enum for cleaner, more idiomatic Django. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single query instead of per-row save loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
maildev is always available via docker-compose, no need for env var configurability here. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 47 out of 51 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.













Description