from typing import Any from django.contrib import admin from django.contrib.admin.views.main import ChangeList from django.db import models from django.db.models import QuerySet from django.http import HttpRequest from django.urls import reverse from .models import ExternalReservation, Reservation, Resource, UserReservation @admin.register(Resource) class ResourceAdmin(admin.ModelAdmin): list_display = ["name", "parent", "min_length", "max_length"] list_filter = ["parent"] search_fields = ["name"] show_facets = admin.ShowFacets.ALWAYS class ReservationTypeFilter(admin.SimpleListFilter): """Filter by subclass""" title = "Reservation Type" parameter_name = "type" # TODO: this could be automatic _subtypes = { "eventmeetingtime": "Event Meeting Time", "userreservation": "User Reservation", "externalreservation": "External Reservation", } def lookups( self, request: HttpRequest, model_admin: admin.ModelAdmin ) -> list[tuple[str, str]]: return [ ("generic", "Generic Reservation"), ] + list(self._subtypes.items()) def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet: if self.value() in self._subtypes: return queryset.filter(**{f"{self.value()}__isnull": False}) elif self.value() == "generic": return queryset.filter( **{f"{subtype}__isnull": True for subtype in self._subtypes} ) else: return queryset class SubclassChangeList(ChangeList): def url_for_result(self, result: models.Model) -> str: opts = type(result)._meta return reverse( f"admin:{opts.app_label}_{opts.model_name}_change", args=(result.pk,), current_app=self.model_admin.admin_site.name, ) @admin.register(Reservation) class ReservationAdmin(admin.ModelAdmin): list_display = ["_title", "_resources", "start", "end"] readonly_fields = ["google_calendar_event_id"] list_filter = ["resources", ReservationTypeFilter] show_facets = admin.ShowFacets.ALWAYS date_hierarchy = "start" def get_queryset(self, request): return ( super() .get_queryset(request) .select_related("eventmeetingtime__event") .prefetch_related("resources") .select_subclasses() ) @admin.display() def _title(self, obj: Reservation): return obj.get_title() @admin.display() def _resources(self, obj: Reservation): return list(obj.resources.all()) or None def get_changelist(self, request: HttpRequest, **kwargs: Any) -> type[ChangeList]: return SubclassChangeList @admin.register(UserReservation) class UserReservationAdmin(admin.ModelAdmin): def has_module_permission(self, request: HttpRequest) -> bool: return False @admin.register(ExternalReservation) class ExternalReservationAdmin(admin.ModelAdmin): def has_module_permission(self, request: HttpRequest) -> bool: return False