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")