Moved Song/Artist changes to generic function.

This commit is contained in:
RecursiveGreen 2018-01-14 18:38:14 -05:00
parent a7ccb61e07
commit 476ddb7a5a
7 changed files with 106 additions and 83 deletions

View file

@ -78,14 +78,26 @@ def naturalize(text):
return text return text
def build_message_start(quantity, model): def quantify(quantity, model):
""" """
The beggining of a message based on the quantity and singular/plural name A message based on the quantity and singular/plural name of the model.
of the model involved.
""" """
if quantity == 1: if quantity == 1:
message = '1 {} was'.format(model._meta.verbose_name) message = '1 {}'.format(model._meta.verbose_name)
else: else:
message = '{} {} were'.format(str(quantity), message = '{} {}'.format(str(quantity),
model._meta.verbose_name_plural) model._meta.verbose_name_plural)
return message return message
def create_success_message(parent_model, parent_quantity, child_model,
child_quantity, remove=False):
"""
Creates a message for displaying the success of model modification.
"""
p_message = quantify(parent_quantity, parent_model)
c_message = quantify(child_quantity, child_model)
if remove:
return '{} successfully removed from {}'.format(c_message, p_message)
else:
return '{} successfully added to {}.'.format(c_message, p_message)

View file

@ -1,10 +1,63 @@
from django.contrib import messages from django.contrib import messages
from django.forms import inlineformset_factory
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.utils import timezone from django.utils import timezone
from core.utils import build_message_start from core.utils import create_success_message, quantify
def change_m2m_items(request, queryset, parent_model, m2m_field,
child_field, calling_function, remove=False):
through_model = getattr(parent_model, m2m_field)
ItemFormSet = inlineformset_factory(parent_model,
through_model.through,
fields=(child_field,),
can_delete=False,
extra=10,)
# If we clicked Submit, then continue. . .
if 'apply' in request.POST:
# Fill the formset with values from the POST request
item_formset = ItemFormSet(request.POST)
# Will only returned "cleaned_data" if form is valid, so check
if item_formset.is_valid():
# Remove the empty form data from the list
data = list(filter(None, item_formset.cleaned_data))
for child in data:
for parent in queryset:
through = getattr(parent, m2m_field)
if request.POST['removal'] == 'True':
through.remove(child[child_field])
else:
through.add(child[child_field])
# Return with informative success message and counts
message = create_success_message(parent_model,
queryset.count(),
through_model.field.related_model,
len(data),
request.POST['removal'] == 'True')
messages.success(request, message)
return HttpResponseRedirect(request.get_full_path())
else:
messages.error(request, "See below for errors in the form.")
# . . .otherwise, create empty formset.
else:
item_formset = ItemFormSet()
return render(request,
'admin/change_m2m_intermediate.html',
{'calling_function': calling_function,
'parent_queryset': queryset,
'item_formset': item_formset,
'parent_model': parent_model,
'child_model': through_model.field.related_model,
'is_removal': remove, })
def publish_items(request, queryset): def publish_items(request, queryset):
rows_updated = queryset.update(published_date=timezone.now()) rows_updated = queryset.update(published_date=timezone.now())
message = build_message_start(rows_updated, queryset.model) message = quantify(rows_updated, queryset.model)
messages.success(request, '{} successfully published.'.format(message)) messages.success(request, '{} successfully published.'.format(message))

View file

@ -1,11 +1,8 @@
from django.contrib import admin, messages from django.contrib import admin
from django.db import models from django.db import models
from django.forms import TextInput from django.forms import TextInput
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .actions import publish_items from .actions import change_m2m_items, publish_items
from .forms import ArtistFormSet
from .models import Album, Artist, Game, Song from .models import Album, Artist, Game, Song
@ -158,61 +155,14 @@ class SongAdmin(admin.ModelAdmin):
def artist_list(self, obj): def artist_list(self, obj):
return ', '.join([a.full_name for a in obj.artists.all()]) return ', '.join([a.full_name for a in obj.artists.all()])
def change_artists(self, request, queryset, remove=False):
artist_formset = None
# If we clicked Submit, 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, so check
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:
if request.POST['removal'] == 'True':
song.artists.remove(artist['artist'])
else:
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]
if request.POST['removal'] == 'True':
act_msg = 'removed from'
else:
act_msg = 'added to'
self.message_user(request,
'{} successfully {} {}.'.format(a_msg,
act_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/change_artists_intermediate.html',
{'songs': queryset,
'artist_formset': artist_formset,
'is_removal': remove, })
def add_artists(self, request, queryset): def add_artists(self, request, queryset):
return self.change_artists(request, queryset) return change_m2m_items(request, queryset, Song, 'artists',
'artist', 'add_artists')
add_artists.short_description = "Add artists to selected items" add_artists.short_description = "Add artists to selected items"
def remove_artists(self, request, queryset): def remove_artists(self, request, queryset):
return self.change_artists(request, queryset, remove=True) return change_m2m_items(request, queryset, Song, 'artists',
'artist', 'remove_artists', remove=True)
remove_artists.short_description = "Remove artists from selected items" remove_artists.short_description = "Remove artists from selected items"
def publish_songs(self, request, queryset): def publish_songs(self, request, queryset):

View file

@ -1,10 +0,0 @@
from django.forms import inlineformset_factory
from .models import Song
ArtistFormSet = inlineformset_factory(Song,
Song.artists.through,
fields=('artist',),
can_delete=False,
extra=10,)

View file

@ -1,18 +1,19 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load model_names %}
{% block content %} {% block content %}
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}
{{ artist_formset.management_form }} {{ item_formset.management_form }}
<table> <table>
<thead> <thead>
<tr> <tr>
<th colspan="2"> <th colspan="2">
<p>Select up to ten artists to {% if is_removal %}remove from{% else %}add to{% endif %} the songs below:</p> <p>Select up to ten {% model_name_plural child_model %} to {% if is_removal %}remove from{% else %}add to{% endif %} the {% model_name_plural parent_model %} below:</p>
</th> </th>
</tr> </tr>
</thead> </thead>
{% for form in artist_formset %} {% for form in item_formset %}
{{ form }} {{ form }}
{% endfor %} {% endfor %}
</table> </table>
@ -20,25 +21,25 @@
<thead> <thead>
<tr> <tr>
<th> <th>
<p>Artists will be {% if is_removal %}removed from{% else %}added to{% endif %} the following songs:</p> <p>{% filter capfirst %}{% model_name_plural child_model %}{% endfilter %} will be {% if is_removal %}removed from{% else %}added to{% endif %} the following {% model_name_plural parent_model %}:</p>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for song in songs %} {% for parent in parent_queryset %}
<tr> <tr>
<th> <th>
{{ song }} {{ parent }}
<input type="hidden" name="_selected_action" value="{{ song.pk }}" /> <input type="hidden" name="_selected_action" value="{{ parent.pk }}" />
</th> </th>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<input type="hidden" name="action" value="{% if is_removal %}remove_artists{% else %}add_artists{% endif %}" /> <input type="hidden" name="action" value="{{ calling_function }}" />
<input type="hidden" name="removal" value="{{ is_removal }}" /> <input type="hidden" name="removal" value="{{ is_removal }}" />
<a href="./"><input type="button" name="Cancel" value="Cancel"></a> <a href="./"><input type="button" name="Cancel" value="Cancel"></a>
<input type="submit" name="apply" value="{% if is_removal %}Remove{% else %}Add{% endif %} Artists" /> <input type="submit" name="apply" value="{% if is_removal %}Remove{% else %}Add{% endif %} {% filter capfirst %}{% model_name_plural child_model %}{% endfilter %}" />
</form> </form>
{% endblock %} {% endblock %}

View file

@ -0,0 +1,17 @@
from django import template
register = template.Library()
@register.simple_tag
def model_name(value):
if hasattr(value, 'model'):
value = value.model
return value._meta.verbose_name
@register.simple_tag
def model_name_plural(value):
if hasattr(value, 'model'):
value = value.model
return value._meta.verbose_name_plural