Files
hoopscout/apps/scouting/views.py
2026-03-13 14:40:38 +01:00

167 lines
6.2 KiB
Python

from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import IntegrityError
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import timezone
from django.views import View
from django.views.generic import ListView, TemplateView, UpdateView
from .forms import SavedSearchForm, SavedSearchUpdateForm
from .models import FavoritePlayer, SavedSearch
from .services.saved_searches import extract_filters_from_params, saved_search_to_querystring
class ScoutingHomeView(LoginRequiredMixin, TemplateView):
template_name = "scouting/index.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["saved_searches"] = SavedSearch.objects.filter(user=self.request.user).order_by("-updated_at")
context["favorites"] = (
FavoritePlayer.objects.filter(user=self.request.user)
.select_related("player", "player__nationality", "player__nominal_position", "player__inferred_role")
.order_by("-created_at")
)
return context
class SavedSearchCreateView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs):
form = SavedSearchForm(request.POST)
if not form.is_valid():
if request.headers.get("HX-Request") == "true":
return render(
request,
"scouting/partials/save_search_feedback.html",
{"ok": False, "message": "Invalid name or visibility values."},
)
messages.error(request, "Could not save search.")
return redirect("players:index")
filters = extract_filters_from_params(request.POST)
if not filters:
message = "No valid filters to save from current search."
if request.headers.get("HX-Request") == "true":
return render(
request,
"scouting/partials/save_search_feedback.html",
{"ok": False, "message": message},
)
messages.error(request, message)
return redirect("players:index")
saved_search = form.save(commit=False)
saved_search.user = request.user
saved_search.filters = filters
try:
saved_search.save()
except IntegrityError:
message = "A saved search with this name already exists."
if request.headers.get("HX-Request") == "true":
return render(
request,
"scouting/partials/save_search_feedback.html",
{"ok": False, "message": message},
)
messages.error(request, message)
return redirect("players:index")
message = f"Saved search '{saved_search.name}' created."
if request.headers.get("HX-Request") == "true":
return render(
request,
"scouting/partials/save_search_feedback.html",
{"ok": True, "message": message},
)
messages.success(request, message)
return redirect("scouting:index")
class SavedSearchUpdateView(LoginRequiredMixin, UpdateView):
model = SavedSearch
form_class = SavedSearchUpdateForm
template_name = "scouting/saved_search_edit.html"
def get_queryset(self):
return SavedSearch.objects.filter(user=self.request.user)
def get_success_url(self):
messages.success(self.request, "Saved search updated.")
return reverse("scouting:index")
class SavedSearchDeleteView(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
saved_search = get_object_or_404(SavedSearch, pk=pk, user=request.user)
saved_search.delete()
if request.headers.get("HX-Request") == "true":
saved_searches = SavedSearch.objects.filter(user=request.user).order_by("-updated_at")
return render(
request,
"scouting/partials/saved_search_table.html",
{"saved_searches": saved_searches},
)
messages.success(request, "Saved search deleted.")
return redirect("scouting:index")
class SavedSearchRunView(LoginRequiredMixin, View):
def get(self, request, pk, *args, **kwargs):
saved_search = get_object_or_404(SavedSearch, pk=pk, user=request.user)
query = saved_search_to_querystring(saved_search.filters)
saved_search.last_run_at = timezone.now()
saved_search.save(update_fields=["last_run_at"])
target = reverse("players:index")
return redirect(f"{target}?{query}" if query else target)
class WatchlistView(LoginRequiredMixin, ListView):
model = FavoritePlayer
context_object_name = "favorites"
template_name = "scouting/watchlist.html"
def get_queryset(self):
return (
FavoritePlayer.objects.filter(user=self.request.user)
.select_related("player", "player__nationality", "player__nominal_position", "player__inferred_role")
.order_by("-created_at")
)
class FavoriteToggleView(LoginRequiredMixin, View):
def post(self, request, player_id, *args, **kwargs):
from apps.players.models import Player
player = get_object_or_404(Player, pk=player_id)
next_url = request.POST.get("next") or request.META.get("HTTP_REFERER") or reverse("players:index")
favorite, created = FavoritePlayer.objects.get_or_create(user=request.user, player=player)
if not created:
favorite.delete()
is_favorite = created
if request.headers.get("HX-Request") == "true":
return render(
request,
"scouting/partials/favorite_button.html",
{
"player": player,
"is_favorite": is_favorite,
"next_url": next_url,
},
)
return redirect(next_url)
class SavedSearchListView(LoginRequiredMixin, ListView):
model = SavedSearch
context_object_name = "saved_searches"
template_name = "scouting/saved_search_list.html"
def get_queryset(self):
return SavedSearch.objects.filter(user=self.request.user).order_by("-updated_at")