from typing import Any from django.contrib import admin from django.http import HttpRequest from django.http import HttpResponse from django.urls import path from django.urls import reverse from django.shortcuts import render from django.utils.html import format_html from music.models import Track from music.models import Album from music.models import Artist from music.models import MusicLog from music.models import Playlist from music.models import RecommendationPlaylist @admin.register(Track) class TrackAdmin(admin.ModelAdmin): class Media: js = ("admin/js/upload_progress.js",) css = {"all": ("admin/css/upload_progress.css",)} list_display = ("album__artist__name", "album__name", "title", "created_by", "created_at") search_fields = ("title", "album__artist__name", "album__name") list_filter = ("album__artist__name", "album__name", "created_at") class TrackInline(admin.TabularInline): model = Track extra = 1 show_change_link = True def has_change_permission( self, request: HttpRequest, obj: Any | None = None ) -> bool: return False def has_add_permission(self, request: HttpRequest, obj: Any | None = None) -> bool: return False @admin.register(Album) class AlbumAdmin(admin.ModelAdmin): list_display = ("artist__name", "name") search_fields = ("artist__name", "name") list_filter = ("artist__name",) inlines = [TrackInline] readonly_fields = ("add_music_track_link",) def add_music_track_link(self, obj: Any | None) -> str: if obj is None or not obj.pk: return "" url = reverse("admin:music_track_add") + f"?album={obj.pk}" return format_html('Add Music Track', url) add_music_track_link.short_description = "Add Music Track" class AlbumInline(admin.TabularInline): model = Album extra = 1 fields = ("name",) show_change_link = True def has_change_permission( self, request: HttpRequest, obj: Any | None = None ) -> bool: return False def has_add_permission(self, request: HttpRequest, obj: Any | None = None) -> bool: return False @admin.register(Artist) class ArtistAdmin(admin.ModelAdmin): list_display = ("name",) search_fields = ("name",) inlines = [AlbumInline] readonly_fields = ("add_album_link",) def add_album_link(self, obj: Any | None) -> str: if obj is None or not obj.pk: return "" url = reverse("admin:music_album_add") + f"?artist={obj.pk}" return format_html('Add Album', url) add_album_link.short_description = "Add Album" @admin.register(Playlist) class PlaylistAdmin(admin.ModelAdmin): list_display = ("name", "created_by", "created_at") search_fields = ("name",) list_filter = ("created_at",) filter_horizontal = ("tracks",) @admin.register(RecommendationPlaylist) class RecommendationPlaylistAdmin(admin.ModelAdmin): list_display = ("name", "is_actual", "created_by", "created_at") search_fields = ("name",) list_filter = ("is_actual", "created_at") actions = ["make_actual"] @admin.action(description="Set selected recommendation playlists as actual") def make_actual(self, request: HttpRequest, queryset: Any) -> None: for recommendation in queryset: recommendation.switch_actual() @admin.register(MusicLog) class MusicLogAdmin(admin.ModelAdmin): list_display = ("track", "played_at") search_fields = ("track__title", "track__album__artist__name", "track__album__name") list_filter = ("played_at",) readonly_fields = ("track", "played_at") change_list_template = "admin/musiclog/change_list.html" def get_urls(self): urls = super().get_urls() custom_urls = [ path("statistics/", self.admin_site.admin_view(self.get_statistic_view), name="musiclog_statistics"), ] return custom_urls + urls def get_statistic_view(self, request: HttpRequest) -> HttpResponse: return render(request, "admin/musiclog/statistics.html")