from django.conf import settings from django.contrib import admin from django.db.models import Count, F from django.urls import reverse from django.utils.html import format_html from django.utils.translation import gettext as _ from furl import furl from rest_framework.reverse import reverse as drf_reverse from .models import Album, Artist, Track # test.. def get_api_url(obj, view="detail", params=None, title=None, request=None): path = drf_reverse( f"{obj._meta.model_name}-{view}", kwargs={ "uuid": obj.uuid, "version": settings.REST_FRAMEWORK["DEFAULT_VERSION"], }, request=request, ) if params: path = furl(path).set(params).url return format_html('{1}', path, title or str(obj)) def get_admin_url(obj, view="change", params=None, title=None): path = reverse( f"admin:{obj._meta.app_label}_{obj._meta.model_name}_{view}", kwargs={"object_id": obj.pk} if view == "change" else {}, ) if params: path = furl(path).set(params).url return format_html('{1}', path, title or str(obj)) class ArtistDecadeActiveListFilter(admin.SimpleListFilter): title = _("decade active") parameter_name = "decade_active" def lookups(self, request, model_admin): return ( ("1980", _("1980s")), ("1990", _("1990s")), ("2000", _("2000s")), ("2010", _("2010s")), ("2020", _("2020s")), ) def queryset(self, request, queryset): try: year_since = int(self.value()) year_until = year_since + 10 except (TypeError, ValueError): return queryset return queryset.filter( albums__year__gte=year_since, albums__year__lt=year_until ) class ArtistAlbumInline(admin.TabularInline): model = Album fields = ("name", "year", "album_admin_link", "tracks_admin_link") readonly_fields = ("album_admin_link", "tracks_admin_link") extra = 0 def get_queryset(self, request): queryset = super().get_queryset(request) return queryset.annotate(track_count=Count("tracks")) def album_admin_link(self, album): return get_admin_url(album) album_admin_link.short_description = _("Album") def tracks_admin_link(self, album): return get_admin_url( Track, view="changelist", params={"album": album.pk}, title=album.track_count, ) tracks_admin_link.short_description = _("Tracks") class AlbumTrackInline(admin.TabularInline): model = Track fields = ("number", "name") extra = 0 @admin.register(Artist) class ArtistAdmin(admin.ModelAdmin): list_display = ("name", "albums_admin_link") list_filter = (ArtistDecadeActiveListFilter,) fields = ("name", "uuid", "albums_admin_link", "artist_api_link") readonly_fields = ("uuid", "albums_admin_link", "artist_api_link") search_fields = ("uuid", "name") inlines = (ArtistAlbumInline,) def get_queryset(self, request): self.request = request queryset = super().get_queryset(request) return queryset.prefetch_related("albums").annotate(album_count=Count("albums")) def albums_admin_link(self, artist): return get_admin_url( Album, view="changelist", params={"artist": artist.pk}, title=artist.album_count, ) albums_admin_link.short_description = _("Albums") albums_admin_link.admin_order_field = "album_count" def artist_api_link(self, artist): return get_api_url(artist, request=self.request) artist_api_link.short_description = _("API") @admin.register(Album) class AlbumAdmin(admin.ModelAdmin): list_display = ("name", "artist_admin_link", "album_year", "tracks_admin_link") list_filter = ("year",) search_fields = ("uuid", "name", "artist__name") fields = ( "name", "year", "uuid", "artist_admin_link", "tracks_admin_link", "album_api_link", ) readonly_fields = ( "uuid", "tracks_admin_link", "artist_admin_link", "album_api_link", ) list_select_related = ("artist",) inlines = (AlbumTrackInline,) def get_queryset(self, request): self.request = request queryset = super().get_queryset(request) return queryset.annotate(track_count=Count("tracks")) def album_year(self, album): return get_admin_url( Album, view="changelist", params={"year": album.year}, title=album.year ) album_year.short_description = _("Year") album_year.admin_order_field = "year" def artist_admin_link(self, album): return get_admin_url(album.artist) artist_admin_link.short_description = _("Artist") artist_admin_link.admin_order_field = "artist__name" def tracks_admin_link(self, album): return get_admin_url( Track, view="changelist", params={"album": album.pk}, title=album.track_count, ) tracks_admin_link.short_description = _("Tracks") tracks_admin_link.admin_order_field = "track_count" def album_api_link(self, album): return get_api_url(album, request=self.request) album_api_link.short_description = _("API") @admin.register(Track) class TrackAdmin(admin.ModelAdmin): list_display = ("name", "artist_admin_link", "album_admin_link", "album_year") list_filter = ("album__year",) search_fields = ("uuid", "name", "album__name", "album__artist__name") fields = ( "name", "uuid", "artist_admin_link", "album_admin_link", "album_year", "track_api_link", ) readonly_fields = ( "uuid", "artist_admin_link", "album_admin_link", "album_year", "track_api_link", ) list_select_related = ("album", "album__artist") ordering = ("name", "album__artist__name", "album__name") def get_queryset(self, request): self.request = request queryset = super().get_queryset(request) return queryset.annotate(album_year=F("album__year")) def album_admin_link(self, track): return get_admin_url(track.album) album_admin_link.short_description = _("Album") album_admin_link.admin_order_field = "album__name" def artist_admin_link(self, track): return get_admin_url(track.album.artist) artist_admin_link.short_description = _("Artist") artist_admin_link.admin_order_field = "album__artist__name" def album_year(self, track): return get_admin_url( Track, view="changelist", params={"album__year": track.album_year}, title=track.album_year, ) album_year.short_description = _("Year") album_year.admin_order_field = "album__year" def track_api_link(self, track): return get_api_url(track, request=self.request) track_api_link.short_description = _("API")