Most of the songs in rotation are DJPick. That is, they aren’t real songs, but instead are markers for a pop-up menu on the playlist. They should be deleted when they are no longer in rotation. So RotationSongFormSet
mentioned yesterday has can_delete = True
. The problem is we don’t want to be able to delete all the songs. So how do we determine which songs to delete? Override add_fields
. This is another reason not to use formset factories. The existing add_fields
adds id
, ORDER
, and DELETE
fields as necessary. We don’t actually want to remove the DELETE
field — since BaseModelFormSet
assumes it’s there and will fail without it — we just want to nerf it. So we change it.
def add_fields(self, form, i): super(RotationSongFormSet, self).add_fields(form, i) if not form.instance.can_delete(): form.fields['DELETE'].widget = forms.forms.HiddenInput() form.fields['DELETE'].clean = lambda a: False
This works. The checkmark isn’t shown and if a value is returned, it still returns false.
Awesome! We can port this to other places that would like to delete songs, like the album admin view. All we have to do is add add_fields
to our SongInline
. Actually, no. Admin inlines are not derived from ModelFormSets
despite all of the similarities. Most of the arguments are the same, because they get passed to the formset factory. Fortunately, we can use a different base ModelFormSet
. And since this code is so useful anyways, I already put it into dj_pro.forms.SongSet
. Now all of the code for editing songs allows you to delete it, but only when appropriate.