admin.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. from django.conf import settings
  2. from django.contrib import admin
  3. from django.db.models import Count, F
  4. from django.urls import reverse
  5. from django.utils.html import format_html
  6. from django.utils.translation import gettext as _
  7. from furl import furl
  8. from rest_framework.reverse import reverse as drf_reverse
  9. from .models import Album, Artist, Track
  10. # test..
  11. def get_api_url(obj, view="detail", params=None, title=None, request=None):
  12. path = drf_reverse(
  13. f"{obj._meta.model_name}-{view}",
  14. kwargs={
  15. "uuid": obj.uuid,
  16. "version": settings.REST_FRAMEWORK["DEFAULT_VERSION"],
  17. },
  18. request=request,
  19. )
  20. if params:
  21. path = furl(path).set(params).url
  22. return format_html('<a href="{0}" title="{1}">{1}</a>', path, title or str(obj))
  23. def get_admin_url(obj, view="change", params=None, title=None):
  24. path = reverse(
  25. f"admin:{obj._meta.app_label}_{obj._meta.model_name}_{view}",
  26. kwargs={"object_id": obj.pk} if view == "change" else {},
  27. )
  28. if params:
  29. path = furl(path).set(params).url
  30. return format_html('<a href="{0}" title="{1}">{1}</a>', path, title or str(obj))
  31. class ArtistDecadeActiveListFilter(admin.SimpleListFilter):
  32. title = _("decade active")
  33. parameter_name = "decade_active"
  34. def lookups(self, request, model_admin):
  35. return (
  36. ("1980", _("1980s")),
  37. ("1990", _("1990s")),
  38. ("2000", _("2000s")),
  39. ("2010", _("2010s")),
  40. ("2020", _("2020s")),
  41. )
  42. def queryset(self, request, queryset):
  43. try:
  44. year_since = int(self.value())
  45. year_until = year_since + 10
  46. except (TypeError, ValueError):
  47. return queryset
  48. return queryset.filter(
  49. albums__year__gte=year_since, albums__year__lt=year_until
  50. )
  51. class ArtistAlbumInline(admin.TabularInline):
  52. model = Album
  53. fields = ("name", "year", "album_admin_link", "tracks_admin_link")
  54. readonly_fields = ("album_admin_link", "tracks_admin_link")
  55. extra = 0
  56. def get_queryset(self, request):
  57. queryset = super().get_queryset(request)
  58. return queryset.annotate(track_count=Count("tracks"))
  59. def album_admin_link(self, album):
  60. return get_admin_url(album)
  61. album_admin_link.short_description = _("Album")
  62. def tracks_admin_link(self, album):
  63. return get_admin_url(
  64. Track,
  65. view="changelist",
  66. params={"album": album.pk},
  67. title=album.track_count,
  68. )
  69. tracks_admin_link.short_description = _("Tracks")
  70. class AlbumTrackInline(admin.TabularInline):
  71. model = Track
  72. fields = ("number", "name")
  73. extra = 0
  74. @admin.register(Artist)
  75. class ArtistAdmin(admin.ModelAdmin):
  76. list_display = ("name", "albums_admin_link")
  77. list_filter = (ArtistDecadeActiveListFilter,)
  78. fields = ("name", "uuid", "albums_admin_link", "artist_api_link")
  79. readonly_fields = ("uuid", "albums_admin_link", "artist_api_link")
  80. search_fields = ("uuid", "name")
  81. inlines = (ArtistAlbumInline,)
  82. def get_queryset(self, request):
  83. self.request = request
  84. queryset = super().get_queryset(request)
  85. return queryset.prefetch_related("albums").annotate(album_count=Count("albums"))
  86. def albums_admin_link(self, artist):
  87. return get_admin_url(
  88. Album,
  89. view="changelist",
  90. params={"artist": artist.pk},
  91. title=artist.album_count,
  92. )
  93. albums_admin_link.short_description = _("Albums")
  94. albums_admin_link.admin_order_field = "album_count"
  95. def artist_api_link(self, artist):
  96. return get_api_url(artist, request=self.request)
  97. artist_api_link.short_description = _("API")
  98. @admin.register(Album)
  99. class AlbumAdmin(admin.ModelAdmin):
  100. list_display = ("name", "artist_admin_link", "album_year", "tracks_admin_link")
  101. list_filter = ("year",)
  102. search_fields = ("uuid", "name", "artist__name")
  103. fields = (
  104. "name",
  105. "year",
  106. "uuid",
  107. "artist_admin_link",
  108. "tracks_admin_link",
  109. "album_api_link",
  110. )
  111. readonly_fields = (
  112. "uuid",
  113. "tracks_admin_link",
  114. "artist_admin_link",
  115. "album_api_link",
  116. )
  117. list_select_related = ("artist",)
  118. inlines = (AlbumTrackInline,)
  119. def get_queryset(self, request):
  120. self.request = request
  121. queryset = super().get_queryset(request)
  122. return queryset.annotate(track_count=Count("tracks"))
  123. def album_year(self, album):
  124. return get_admin_url(
  125. Album, view="changelist", params={"year": album.year}, title=album.year
  126. )
  127. album_year.short_description = _("Year")
  128. album_year.admin_order_field = "year"
  129. def artist_admin_link(self, album):
  130. return get_admin_url(album.artist)
  131. artist_admin_link.short_description = _("Artist")
  132. artist_admin_link.admin_order_field = "artist__name"
  133. def tracks_admin_link(self, album):
  134. return get_admin_url(
  135. Track,
  136. view="changelist",
  137. params={"album": album.pk},
  138. title=album.track_count,
  139. )
  140. tracks_admin_link.short_description = _("Tracks")
  141. tracks_admin_link.admin_order_field = "track_count"
  142. def album_api_link(self, album):
  143. return get_api_url(album, request=self.request)
  144. album_api_link.short_description = _("API")
  145. @admin.register(Track)
  146. class TrackAdmin(admin.ModelAdmin):
  147. list_display = ("name", "artist_admin_link", "album_admin_link", "album_year")
  148. list_filter = ("album__year",)
  149. search_fields = ("uuid", "name", "album__name", "album__artist__name")
  150. fields = (
  151. "name",
  152. "uuid",
  153. "artist_admin_link",
  154. "album_admin_link",
  155. "album_year",
  156. "track_api_link",
  157. )
  158. readonly_fields = (
  159. "uuid",
  160. "artist_admin_link",
  161. "album_admin_link",
  162. "album_year",
  163. "track_api_link",
  164. )
  165. list_select_related = ("album", "album__artist")
  166. ordering = ("name", "album__artist__name", "album__name")
  167. def get_queryset(self, request):
  168. self.request = request
  169. queryset = super().get_queryset(request)
  170. return queryset.annotate(album_year=F("album__year"))
  171. def album_admin_link(self, track):
  172. return get_admin_url(track.album)
  173. album_admin_link.short_description = _("Album")
  174. album_admin_link.admin_order_field = "album__name"
  175. def artist_admin_link(self, track):
  176. return get_admin_url(track.album.artist)
  177. artist_admin_link.short_description = _("Artist")
  178. artist_admin_link.admin_order_field = "album__artist__name"
  179. def album_year(self, track):
  180. return get_admin_url(
  181. Track,
  182. view="changelist",
  183. params={"album__year": track.album_year},
  184. title=track.album_year,
  185. )
  186. album_year.short_description = _("Year")
  187. album_year.admin_order_field = "album__year"
  188. def track_api_link(self, track):
  189. return get_api_url(track, request=self.request)
  190. track_api_link.short_description = _("API")