From 65fb7d9f15e12b303b3a27f566a9a4355cfbb6bb Mon Sep 17 00:00:00 2001 From: Josh Washburne Date: Fri, 12 Jan 2018 16:35:25 -0500 Subject: [PATCH] Add admin actions for adding/removing multiple artists to songs. --- savepointradio/radio/admin.py | 96 +++++++++++++++++-- savepointradio/radio/forms.py | 10 ++ .../admin/add_artists_intermediate.html | 43 +++++++++ .../admin/remove_artists_intermediate.html | 43 +++++++++ 4 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 savepointradio/radio/forms.py create mode 100644 savepointradio/radio/templates/admin/add_artists_intermediate.html create mode 100644 savepointradio/radio/templates/admin/remove_artists_intermediate.html diff --git a/savepointradio/radio/admin.py b/savepointradio/radio/admin.py index 080e4f0..1445c41 100644 --- a/savepointradio/radio/admin.py +++ b/savepointradio/radio/admin.py @@ -1,8 +1,11 @@ -from django.contrib import admin +from django.contrib import admin, messages from django.db import models from django.forms import TextInput +from django.http import HttpResponseRedirect +from django.shortcuts import render from django.utils import timezone +from .forms import ArtistFormSet from .models import Album, Artist, Game, Song @@ -15,8 +18,6 @@ class ArtistInline(admin.TabularInline): @admin.register(Album) class AlbumAdmin(admin.ModelAdmin): - ordering = ("sorted_title",) - # Detail List display list_display = ('title', '_is_enabled', '_is_published') search_fields = ['title'] @@ -50,8 +51,6 @@ class AlbumAdmin(admin.ModelAdmin): @admin.register(Artist) class ArtistAdmin(admin.ModelAdmin): - ordering = ("sorted_full_name",) - # Detail List display list_display = ('first_name', 'alias', @@ -89,8 +88,6 @@ class ArtistAdmin(admin.ModelAdmin): @admin.register(Game) class GameAdmin(admin.ModelAdmin): - ordering = ("sorted_title",) - # Detail List display list_display = ('title', '_is_enabled', '_is_published') search_fields = ['title'] @@ -124,8 +121,6 @@ class GameAdmin(admin.ModelAdmin): @admin.register(Song) class SongAdmin(admin.ModelAdmin): - ordering = ("sorted_title",) - formfield_overrides = { models.TextField: {'widget': TextInput(attrs={'size': 160, })}, } @@ -133,11 +128,12 @@ class SongAdmin(admin.ModelAdmin): # Detail List display list_display = ('title', 'game', + 'album', 'artist_list', '_is_enabled', '_is_published') search_fields = ['title'] - actions = ['publish_items'] + actions = ['publish_items', 'add_artists', 'remove_artists'] # Edit Form display exclude = ('artists',) @@ -177,6 +173,86 @@ class SongAdmin(admin.ModelAdmin): def artist_list(self, obj): return ', '.join([a.full_name for a in obj.artists.all()]) + def add_artists(self, request, queryset): + artist_formset = None + + # If we clicked "Add Artists", then continue. . . + if 'apply' in request.POST: + # Fill the formset with values from the POST request + artist_formset = ArtistFormSet(request.POST) + + # Will only returned "cleaned_data" if form is valid + if artist_formset.is_valid(): + # remove the empty form data from the list + data = list(filter(None, artist_formset.cleaned_data)) + + for artist in data: + for song in queryset: + song.artists.add(artist['artist']) + + # Return with informative success message and counts + a_count = len(data) + s_count = queryset.count() + a_msg = ('1 artist was', + '{} artists were'.format(a_count))[a_count > 1] + s_msg = ('1 song', '{} songs'.format(s_count))[s_count > 1] + self.message_user(request, + '{} successfully added to {}.'.format(a_msg, + s_msg)) + return HttpResponseRedirect(request.get_full_path()) + else: + self.message_user(request, + "See below for errors in the form.", + level=messages.ERROR) + # . . .otherwise, create empty formset. + if not artist_formset: + artist_formset = ArtistFormSet() + + return render(request, + 'admin/add_artists_intermediate.html', + {'songs': queryset, 'artist_formset': artist_formset, }) + add_artists.short_description = "Add artists to selected items" + + def remove_artists(self, request, queryset): + artist_formset = None + + # If we clicked "Remove Artists", then continue. . . + if 'apply' in request.POST: + # Fill the formset with values from the POST request + artist_formset = ArtistFormSet(request.POST) + + # Will only returned "cleaned_data" if form is valid + if artist_formset.is_valid(): + # remove the empty form data from the list + data = list(filter(None, artist_formset.cleaned_data)) + + for artist in data: + for song in queryset: + song.artists.remove(artist['artist']) + + # Return with informative success message and counts + a_count = len(data) + s_count = queryset.count() + a_msg = ('1 artist was', + '{} artists were'.format(a_count))[a_count > 1] + s_msg = ('1 song', '{} songs'.format(s_count))[s_count > 1] + self.message_user(request, + '{} successfully removed from {}.'.format(a_msg, + s_msg)) + return HttpResponseRedirect(request.get_full_path()) + else: + self.message_user(request, + "See below for errors in the form.", + level=messages.ERROR) + # . . .otherwise, create empty formset. + if not artist_formset: + artist_formset = ArtistFormSet() + + return render(request, + 'admin/remove_artists_intermediate.html', + {'songs': queryset, 'artist_formset': artist_formset, }) + remove_artists.short_description = "Remove artists from selected items" + def publish_items(self, request, queryset): rows_updated = queryset.update(published_date=timezone.now()) if rows_updated == 1: diff --git a/savepointradio/radio/forms.py b/savepointradio/radio/forms.py new file mode 100644 index 0000000..065b690 --- /dev/null +++ b/savepointradio/radio/forms.py @@ -0,0 +1,10 @@ +from django.forms import inlineformset_factory + +from .models import Song + + +ArtistFormSet = inlineformset_factory(Song, + Song.artists.through, + fields=('artist',), + can_delete=False, + extra=10,) diff --git a/savepointradio/radio/templates/admin/add_artists_intermediate.html b/savepointradio/radio/templates/admin/add_artists_intermediate.html new file mode 100644 index 0000000..078a35c --- /dev/null +++ b/savepointradio/radio/templates/admin/add_artists_intermediate.html @@ -0,0 +1,43 @@ +{% extends "admin/base_site.html" %} + +{% block content %} +
+ {% csrf_token %} + {{ artist_formset.management_form }} + + + + + + + {% for form in artist_formset %} + {{ form }} + {% endfor %} +
+

Select up to ten artists to add to the songs below:

+
+ + + + + + + + {% for song in songs %} + + + + {% endfor %} + +
+

Artists will be added to the following songs:

+
+ {{ song }} + +
+ + + + +
+{% endblock %} \ No newline at end of file diff --git a/savepointradio/radio/templates/admin/remove_artists_intermediate.html b/savepointradio/radio/templates/admin/remove_artists_intermediate.html new file mode 100644 index 0000000..fb41221 --- /dev/null +++ b/savepointradio/radio/templates/admin/remove_artists_intermediate.html @@ -0,0 +1,43 @@ +{% extends "admin/base_site.html" %} + +{% block content %} +
+ {% csrf_token %} + {{ artist_formset.management_form }} + + + + + + + {% for form in artist_formset %} + {{ form }} + {% endfor %} +
+

Select up to ten artists to remove from the songs below:

+
+ + + + + + + + {% for song in songs %} + + + + {% endfor %} + +
+

Artists will be removed from the following songs:

+
+ {{ song }} + +
+ + + + +
+{% endblock %} \ No newline at end of file