Pārlūkot izejas kodu

rework delete function to handle cases of multiple snippets

LB 7 gadi atpakaļ
vecāks
revīzija
4a3590d53b

+ 29 - 11
wagtail/snippets/templates/wagtailsnippets/snippets/confirm_delete.html

@@ -1,20 +1,38 @@
 {% extends "wagtailadmin/base.html" %}
 {% load wagtailadmin_tags i18n %}
-{% block titletag %}{% blocktrans with snippet_type_name=model_opts.verbose_name %}Delete {{ snippet_type_name }} - {{ instance }}{% endblocktrans %}{% endblock %}
+{% block titletag %}
+    {% if count == 1 %}
+      {% blocktrans with snippet_type_name=model_opts.verbose_name %}Delete {{ snippet_type_name }}{% endblocktrans %} - {{ instances|first }}
+    {% else %}
+      {{ count }} {{ model_opts.verbose_name_plural|capfirst }}
+    {% endif %}
+{% endblock %}
 {% block content %}
-    {% trans "Delete" as delete_str %}
-    {% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=instance icon="snippet" %}
+    {% trans "Delete " as delete_str %}
+    {% if count == 1 %}
+        {% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=instances|first icon="snippet" %}
+    {% else %}
+        {% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=model_opts.verbose_name_plural|capfirst icon="snippet" %}
+    {% endif %}
 
     <div class="nice-padding">
-        {% usage_count_enabled as uc_enabled %}
-        {% if uc_enabled %}
-            <div class="usagecount">
-                <a href="{{ instance.usage_url }}">{% blocktrans count usage_count=instance.get_usage.count %}Used {{ usage_count }} time{% plural %}Used {{ usage_count }} times{% endblocktrans %}</a>
-            </div>
+        {% if count == 1 %}
+            {% usage_count_enabled as uc_enabled %}
+            {% if uc_enabled %}
+                <div class="usagecount">
+                    <a href="{{ instances.0.usage_url }}">{% blocktrans count usage_count=instances.0.get_usage.count %}Used {{ usage_count }} time{% plural %}Used {{ usage_count }} times{% endblocktrans %}</a>
+                </div>
+            {% endif %}
+            <p>{% blocktrans with snippet_type_name=model_opts.verbose_name %}Are you sure you want to delete this {{ snippet_type_name }}?{% endblocktrans %}</p>
+        {% else %}
+            <p>{% blocktrans with snippet_type_name=model_opts.verbose_name_plural %}Are you sure you want to delete {{ count }} {{ snippet_type_name }}?{% endblocktrans %}</p>
+            <ul>
+                {% for instance in instances %}
+                <li>{{ instance }}</li>
+                {% endfor %}
+            </ul>
         {% endif %}
-
-        <p>{% blocktrans with snippet_type_name=model_opts.verbose_name %}Are you sure you want to delete this {{ snippet_type_name }}?{% endblocktrans %}</p>
-        <form action="{% url 'wagtailsnippets:delete' model_opts.app_label model_opts.model_name instance.pk|admin_urlquote %}" method="POST">
+        <form action="{{ submit_url }}" method="POST">
             {% csrf_token %}
             <input type="submit" value="{% trans 'Yes, delete' %}" class="button serious" />
         </form>

+ 79 - 0
wagtail/snippets/tests.py

@@ -366,6 +366,64 @@ class TestSnippetDelete(TestCase, WagtailTestUtils):
         self.assertContains(response, self.test_snippet.usage_url())
 
 
+class TestSnippetDeleteMultipleWithOne(TestCase, WagtailTestUtils):
+    # test deletion of one snippet using the delete-multiple URL
+    # behaviour should mimic the TestSnippetDelete but with different URl structure
+    fixtures = ['test.json']
+
+    def setUp(self):
+        self.snippet = Advert.objects.get(id=1)
+        self.login()
+
+    def test_delete_get(self):
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % (self.snippet.id)
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_delete_post(self):
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % (self.snippet.id)
+        response = self.client.post(url)
+
+        # Should be redirected to explorer page
+        self.assertRedirects(response, reverse('wagtailsnippets:list', args=('tests', 'advert')))
+
+        # Check that the page is gone
+        self.assertEqual(Advert.objects.filter(text='test_advert').count(), 0)
+
+
+class TestSnippetDeleteMultipleWithThree(TestCase, WagtailTestUtils):
+    # test deletion of three snippets using the delete-multiple URL
+    fixtures = ['test.json']
+
+    def setUp(self):
+        # first advert is in the fixtures
+        Advert.objects.create(text="Boreas").save()
+        Advert.objects.create(text="Cloud 9").save()
+        self.snippets = Advert.objects.all()
+        self.login()
+
+    def test_delete_get(self):
+        # tests that the URL is available on get
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % ('&id='.join(['%s' % snippet.id for snippet in self.snippets]))
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_delete_post(self):
+        # tests that the URL is available on post and deletes snippets
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % ('&id='.join(['%s' % snippet.id for snippet in self.snippets]))
+        response = self.client.post(url)
+
+        # Should be redirected to explorer page
+        self.assertRedirects(response, reverse('wagtailsnippets:list', args=('tests', 'advert')))
+
+        # Check that the page is gone
+        self.assertEqual(Advert.objects.filter(text='test_advert').count(), 0)
+
+
 class TestSnippetChooserPanel(TestCase, WagtailTestUtils):
     fixtures = ['test.json']
 
@@ -615,6 +673,13 @@ class TestAddOnlyPermissions(TestCase, WagtailTestUtils):
         # permission should be denied
         self.assertRedirects(response, reverse('wagtailadmin_home'))
 
+    def test_get_delete_mulitple(self):
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % self.test_snippet.id
+        response = self.client.get(url)
+        # permission should be denied
+        self.assertRedirects(response, reverse('wagtailadmin_home'))
+
 
 class TestEditOnlyPermissions(TestCase, WagtailTestUtils):
     fixtures = ['test.json']
@@ -659,6 +724,13 @@ class TestEditOnlyPermissions(TestCase, WagtailTestUtils):
         # permission should be denied
         self.assertRedirects(response, reverse('wagtailadmin_home'))
 
+    def test_get_delete_mulitple(self):
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % self.test_snippet.id
+        response = self.client.get(url)
+        # permission should be denied
+        self.assertRedirects(response, reverse('wagtailadmin_home'))
+
 
 class TestDeleteOnlyPermissions(TestCase, WagtailTestUtils):
     fixtures = ['test.json']
@@ -703,6 +775,13 @@ class TestDeleteOnlyPermissions(TestCase, WagtailTestUtils):
         self.assertEqual(response.status_code, 200)
         self.assertTemplateUsed(response, 'wagtailsnippets/snippets/confirm_delete.html')
 
+    def test_get_delete_mulitple(self):
+        url = reverse('wagtailsnippets:delete-multiple', args=('tests', 'advert'))
+        url += '?id=%s' % self.test_snippet.id
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+        self.assertTemplateUsed(response, 'wagtailsnippets/snippets/confirm_delete.html')
+
 
 class TestSnippetEditHandlers(TestCase, WagtailTestUtils):
     def test_standard_edit_handler(self):

+ 1 - 0
wagtail/snippets/urls.py

@@ -13,6 +13,7 @@ urlpatterns = [
     url(r'^(\w+)/(\w+)/$', snippets.list, name='list'),
     url(r'^(\w+)/(\w+)/add/$', snippets.create, name='add'),
     url(r'^(\w+)/(\w+)/([^/]+?)/$', snippets.edit, name='edit'),
+    url(r'^(\w+)/(\w+)/multiple/delete/$', snippets.delete, name='delete-multiple'),
     url(r'^(\w+)/(\w+)/([^/]+?)/delete/$', snippets.delete, name='delete'),
     url(r'^(\w+)/(\w+)/([^/]+?)/usage/$', snippets.usage, name='usage'),
 ]

+ 29 - 8
wagtail/snippets/views/snippets.py

@@ -1,3 +1,5 @@
+from urllib.parse import urlencode
+
 from django.apps import apps
 from django.contrib.admin.utils import quote, unquote
 from django.http import Http404
@@ -221,29 +223,48 @@ def edit(request, app_label, model_name, pk):
     })
 
 
-def delete(request, app_label, model_name, pk):
+def delete(request, app_label, model_name, pk=None):
     model = get_snippet_model_from_url_params(app_label, model_name)
 
     permission = get_permission_name('delete', model)
     if not request.user.has_perm(permission):
         return permission_denied(request)
 
-    instance = get_object_or_404(model, pk=unquote(pk))
+    if pk:
+        instances = [get_object_or_404(model, pk=unquote(pk))]
+    else:
+        ids = request.GET.getlist('id')
+        instances = model.objects.filter(pk__in=ids)
+
+    count = len(instances)
 
     if request.method == 'POST':
-        instance.delete()
-        messages.success(
-            request,
-            _("{snippet_type} '{instance}' deleted.").format(
+        for instance in instances:
+            instance.delete()
+
+        if count == 1:
+            message_content = _("{snippet_type} '{instance}' deleted.").format(
                 snippet_type=capfirst(model._meta.verbose_name_plural),
                 instance=instance
             )
-        )
+        else:
+            message_content = _("{count} {snippet_type} deleted.").format(
+                snippet_type=capfirst(model._meta.verbose_name_plural),
+                count=count
+            )
+
+        messages.success(request, message_content)
+
         return redirect('wagtailsnippets:list', app_label, model_name)
 
     return render(request, 'wagtailsnippets/snippets/confirm_delete.html', {
         'model_opts': model._meta,
-        'instance': instance,
+        'count': count,
+        'instances': instances,
+        'submit_url': (
+            reverse('wagtailsnippets:delete-multiple', args=(app_label, model_name)) +
+            '?' + urlencode([('id', instance.pk) for instance in instances])
+        ),
     })