Fix RefereeLevel.clean() rejecting a valid inherits_from on create

club_id is still None mid-validation for a brand-new level -- creation
assigns the club in form_valid(), after is_valid() already ran clean().
validate_club_scope only makes sense once club_id is actually set;
skip it on create, where the form's own already-club-scoped
inherits_from queryset is what prevents a cross-club pick anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
2026-08-20 22:47:23 +02:00
parent 66d7de820f
commit d2eced9a50
2 changed files with 22 additions and 1 deletions

View File

@@ -2335,6 +2335,19 @@ class MemberRefereeEligibilityTests(ManagementTestBase):
self.assertContains(response, "Ref Eree")
def test_team_page_lists_a_referee_eligible_via_inheritance(self):
# self.level ("Regional") already qualifies for self.team; a higher
# level that inherits from it (with no teams of its own) should still
# show up here -- see RefereeLevel.eligible_team_ids.
national = RefereeLevel.objects.create(club=self.club, name="National", inherits_from=self.level)
national_ref = Member.objects.create(first_name="Nat", last_name="Ional")
RefereeProfile.objects.create(member=national_ref, level=national, valid_until=self.future_date)
self.client.force_login(self.admin_user)
response = self.club_get("team_detail", self.team.pk)
self.assertContains(response, "Nat Ional")
def test_team_page_excludes_an_expired_referee(self):
# "Ref Eree" alone also matches the (unrelated) add-player/assign-staff
# dropdowns, which list every active club member regardless of referee

View File

@@ -160,7 +160,15 @@ class RefereeLevel(ClubScopedModel):
return self.name
def clean(self):
validate_club_scope(self, self.club_id, same_club_fields=("inherits_from",))
# club_id is still None here for a brand-new level: RefereeLevelCreateView
# (like its siblings -- PositionCreateView, GroupCreateView, ...) assigns
# form.instance.club in form_valid(), *after* the form's is_valid() already
# ran clean() -- so there's nothing to compare against yet on create. The
# form's own inherits_from queryset (scoped to `club`) is what actually
# blocks a cross-club pick there; this still catches it on every other path
# (update, admin, direct .full_clean()) where club_id is already set.
if self.club_id is not None:
validate_club_scope(self, self.club_id, same_club_fields=("inherits_from",))
current = self.inherits_from
seen = set()
while current is not None: