Add a home-location box to the club detail page in the control panel

Setting a club's home ground here creates/updates the same events.Location
row (flagged is_home) that the club's own Teams > Locations page shows and
edits -- no separate sync step, it's the same record either way. Also
fixes the shared form_field templatetag: django-countries' CountryField
widget reports as "lazyselect", which fell through to a broken plain
text input instead of rendering as a dropdown.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R1gj3J1QPfP38XWpnpbFpy
This commit is contained in:
2026-08-04 12:27:48 +02:00
parent e6850232f0
commit 68cad0c951
7 changed files with 167 additions and 3 deletions

View File

@@ -15,9 +15,10 @@ from billing.services import BillingError
from billing.services.dues import next_period_start, open_period, reactivate, record_payment, subscribe, waive
from billing.services.invoices import invoice_pdf, issue_invoice
from club.models import Club, ClubRole
from events.models import Location
from features.models import Maintenance
from .forms import ClubAdminForm, ClubForm, DuePaymentForm, FlagForm, MaintenanceForm, OpenPeriodForm, PlatformAdminForm, SubscriptionForm, TierForm, TierPriceForm
from .forms import ClubAdminForm, ClubForm, DuePaymentForm, FlagForm, HomeLocationForm, MaintenanceForm, OpenPeriodForm, PlatformAdminForm, SubscriptionForm, TierForm, TierPriceForm
from .messages import notify
from .mixins import PlatformStaffRequiredMixin, PlatformSuperuserRequiredMixin, RedirectOnInvalidMixin
from .services.admins import grant_club_admin, revoke_club_admin
@@ -134,7 +135,11 @@ class ClubDetailView(PlatformStaffRequiredMixin, DetailView):
if due.is_owing:
due.payment_form = DuePaymentForm(initial={"amount": due.balance})
home_location = Location.objects.filter(club=self.object, is_home=True).first()
return super().get_context_data(
home_location=home_location,
home_location_form=HomeLocationForm(instance=home_location),
nav="clubs",
groups=club_statistics(self.object),
attention=club_attention(self.object),
@@ -191,6 +196,35 @@ class ClubAdminAddView(PlatformStaffRequiredMixin, RedirectOnInvalidMixin, FormV
return redirect("controlpanel:club_detail", pk=self.kwargs["pk"])
class ClubHomeLocationSetView(PlatformStaffRequiredMixin, RedirectOnInvalidMixin, FormView):
"""Create or update the club's home Location -- reachable only via the "Home
location" modal on the club detail page. Binds to the existing home Location
(if any) so submitting the form edits it in place rather than ever creating
a second one; ``unique_home_location_per_club`` backs that up at the DB level."""
form_class = HomeLocationForm
http_method_names = ["post"]
invalid_redirect_url_name = "controlpanel:club_detail"
@property
def club(self):
return get_object_or_404(Club, pk=self.kwargs["pk"])
def get_invalid_redirect_kwargs(self):
return {"pk": self.kwargs["pk"]}
def get_form_kwargs(self):
return super().get_form_kwargs() | {"instance": Location.objects.filter(club=self.club, is_home=True).first()}
def form_valid(self, form):
location = form.save(commit=False)
location.club = self.club
location.is_home = True
location.save()
notify(self.request, f"s|Home location set|{location} is now {self.club}'s home location.")
return redirect("controlpanel:club_detail", pk=self.kwargs["pk"])
class ClubAdminRemoveView(PlatformStaffRequiredMixin, View):
def post(self, request, pk, role_pk):
role = get_object_or_404(ClubRole, pk=role_pk, club_id=pk, role=ClubRole.Roles.ADMIN)