Repository: carpentries/amy

Issue:
AMYDeleteView and RedirectSupportMixin achieve different redirection
The `next` param to the `AMYDeleteView` is a POST param while to any view subclassing the `RedirectSupportMixin` mixin, the `next` param is a GET param. The two achieve the same thing, but differently.

I propose that we strip the `AMYDeleteView` of any redirect support and use `RedirectSupportMixin` along with `AMYDeleteView`.


Discussion:

Resolving patch:
diff --git a/workshops/base_views.py b/workshops/base_views.py
--- a/workshops/base_views.py
+++ b/workshops/base_views.py
@@ -104,10 +104,7 @@ def delete(self, request, *args, **kwargs):
         # Workaround for https://code.djangoproject.com/ticket/21926
         # Replicates the `delete` method of DeleteMixin
         self.object = self.get_object()
-        if request.POST.get('next', None):
-            success_url = request.POST['next']
-        else:
-            success_url = self.get_success_url()
+        success_url = self.get_success_url()
         try:
             self.object.delete()
             messages.success(
diff --git a/workshops/views.py b/workshops/views.py
--- a/workshops/views.py
+++ b/workshops/views.py
@@ -1576,7 +1576,7 @@ class TaskUpdate(OnlyForAdminsMixin, PermissionRequiredMixin,
 
 
 class TaskDelete(OnlyForAdminsMixin, PermissionRequiredMixin,
-                 AMYDeleteView):
+                 RedirectSupportMixin, AMYDeleteView):
     model = Task
     permission_required = 'workshops.delete_task'
     success_url = reverse_lazy('all_tasks')
@@ -1586,13 +1586,22 @@ class TaskDelete(OnlyForAdminsMixin, PermissionRequiredMixin,
 #------------------------------------------------------------
 
 
-class AwardDelete(OnlyForAdminsMixin, PermissionRequiredMixin,
-                  AMYDeleteView):
+class MockAwardDelete(OnlyForAdminsMixin, PermissionRequiredMixin,
+                      AMYDeleteView):
     model = Award
     permission_required = 'workshops.delete_award'
 
     def get_success_url(self):
-        return reverse('person_edit', args=[self.get_object().person.pk]) + '#awards'
+        return reverse('badge_details', args=[self.get_object().badge.name])
+
+
+class AwardDelete(RedirectSupportMixin, MockAwardDelete):
+    # Modify the MRO to look like:
+    # AwardDelete < RedirectSupportMixin < MockAwardDelete
+    #
+    # This ensures that `super()` when called from `get_success_url` method of
+    # RedirectSupportMixin returns MockAwardDelete
+    pass
 
 
 #------------------------------------------------------------


Test patch:
diff --git a/workshops/test/test_badge.py b/workshops/test/test_badge.py
--- a/workshops/test/test_badge.py
+++ b/workshops/test/test_badge.py
@@ -57,8 +57,15 @@ def test_remove_award(self):
         person = self.hermione
         award = person.award_set.all()[0]
         badge = award.badge
-        # test first URL
-        rv = self.client.post(reverse('award_delete', args=[award.pk, ]))
-        assert rv.status_code == 302
+
+        rv = self.client.post(
+            '{}?next={}'.format(
+                reverse('award_delete', args=[award.pk]),
+                reverse('admin-dashboard'),
+            ),
+            follow=True
+        )
+        self.assertRedirects(rv, reverse('admin-dashboard'))
+
         assert award not in badge.award_set.all()  # award really removed
         assert badge not in person.badges.all()  # badge not avail. via Awards
diff --git a/workshops/test/test_todos.py b/workshops/test/test_todos.py
--- a/workshops/test/test_todos.py
+++ b/workshops/test/test_todos.py
@@ -99,16 +99,9 @@ def test_deleted(self):
             event=event, completed=False, title="Test TODO3",
             due=date.today(), additional="",
         )
-
         assert todo in event.todoitem_set.all()
 
-        rv = self.client.post(
-            reverse('todo_delete', args=[todo.pk]),
-            {'next': reverse('admin-dashboard')},
-            follow=True
-        )
-        self.assertRedirects(rv, reverse('admin-dashboard'))
-
+        rv = self.client.post(reverse('todo_delete', args=[todo.pk]))
         assert event.todoitem_set.all().count() == 0
 
     def test_edited(self):