kopia lustrzana https://github.com/wagtail/wagtail
Fix BaseDeleteView subclassing for Django 4.0
As of Django 4.0 BaseDeleteView has switched to a new implementation based on FormMixin where custom deletion logic now lives in form_valid: https://docs.djangoproject.com/en/4.0/releases/4.0/#deleteview-changes Here we copy the Django 4.0 implementation for use on older Django versions to keep everything consistent, and provide a delete_action method for views that override wagtail.views.generic.models.DeleteView further (e.g. the workflow deactivation views).pull/7568/head
rodzic
44963d87d0
commit
daa46b216c
|
@ -60,3 +60,7 @@ should be rewritten as:
|
|||
```python
|
||||
self.assertEqual(list(page.body[0].value), ['hello', 'goodbye'])
|
||||
```
|
||||
|
||||
### `wagtail.admin.views.generic.DeleteView` follows Django 4.0 conventions
|
||||
|
||||
The internal (undocumented) class-based view `wagtail.admin.views.generic.DeleteView` has been updated to align with [Django 4.0's `DeleteView` implementation](https://docs.djangoproject.com/en/4.0/releases/4.0/#deleteview-changes), which uses `FormMixin` to handle POST requests. Any custom deletion logic in `delete()` handlers should be moved to `form_valid()`.
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
from django import VERSION as DJANGO_VERSION
|
||||
from django.db import transaction
|
||||
from django.forms import Form
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import gettext_lazy
|
||||
from django.views.generic.edit import BaseCreateView, BaseDeleteView, BaseUpdateView
|
||||
from django.views.generic.detail import BaseDetailView
|
||||
from django.views.generic.edit import BaseCreateView
|
||||
from django.views.generic.edit import BaseDeleteView as DjangoBaseDeleteView
|
||||
from django.views.generic.edit import BaseUpdateView, DeletionMixin, FormMixin
|
||||
from django.views.generic.list import BaseListView
|
||||
|
||||
from wagtail.admin import messages
|
||||
|
@ -15,6 +20,39 @@ from .base import WagtailAdminTemplateMixin
|
|||
from .permissions import PermissionCheckedMixin
|
||||
|
||||
|
||||
if DJANGO_VERSION >= (4, 0):
|
||||
BaseDeleteView = DjangoBaseDeleteView
|
||||
else:
|
||||
# As of Django 4.0 BaseDeleteView has switched to a new implementation based on FormMixin
|
||||
# where custom deletion logic now lives in form_valid:
|
||||
# https://docs.djangoproject.com/en/4.0/releases/4.0/#deleteview-changes
|
||||
# Here we define BaseDeleteView to match the Django 4.0 implementation to keep it consistent
|
||||
# across all versions.
|
||||
class BaseDeleteView(DeletionMixin, FormMixin, BaseDetailView):
|
||||
"""
|
||||
Base view for deleting an object.
|
||||
Using this base class requires subclassing to provide a response mixin.
|
||||
"""
|
||||
form_class = Form
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Set self.object before the usual form processing flow.
|
||||
# Inlined because having DeletionMixin as the first base, for
|
||||
# get_success_url(), makes leveraging super() with ProcessFormView
|
||||
# overly complex.
|
||||
self.object = self.get_object()
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
success_url = self.get_success_url()
|
||||
self.object.delete()
|
||||
return HttpResponseRedirect(success_url)
|
||||
|
||||
|
||||
class IndexView(PermissionCheckedMixin, WagtailAdminTemplateMixin, BaseListView):
|
||||
model = None
|
||||
index_url_name = None
|
||||
|
@ -248,11 +286,13 @@ class DeleteView(PermissionCheckedMixin, WagtailAdminTemplateMixin, BaseDeleteVi
|
|||
return None
|
||||
return self.success_message.format(self.object)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
success_url = self.get_success_url()
|
||||
def delete_action(self):
|
||||
with transaction.atomic():
|
||||
log(instance=self.object, action='wagtail.delete')
|
||||
self.object.delete()
|
||||
messages.success(request, self.get_success_message())
|
||||
|
||||
def form_valid(self, form):
|
||||
success_url = self.get_success_url()
|
||||
self.delete_action()
|
||||
messages.success(self.request, self.get_success_message())
|
||||
return HttpResponseRedirect(success_url)
|
||||
|
|
|
@ -231,11 +231,8 @@ class Disable(DeleteView):
|
|||
}
|
||||
return context
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.object.deactivate(user=request.user)
|
||||
messages.success(request, self.get_success_message())
|
||||
return redirect(reverse(self.index_url_name))
|
||||
def delete_action(self):
|
||||
self.object.deactivate(user=self.request.user)
|
||||
|
||||
|
||||
def usage(request, pk):
|
||||
|
@ -460,11 +457,8 @@ class DisableTask(DeleteView):
|
|||
def get_edit_url(self):
|
||||
return reverse(self.edit_url_name, args=(self.kwargs['pk'],))
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.object.deactivate(user=request.user)
|
||||
messages.success(request, self.get_success_message())
|
||||
return redirect(reverse(self.index_url_name))
|
||||
def delete_action(self):
|
||||
self.object.deactivate(user=self.request.user)
|
||||
|
||||
|
||||
@require_POST
|
||||
|
|
|
@ -85,12 +85,12 @@ class DeleteView(generic.DeleteView):
|
|||
context['can_delete'] = self.can_delete(object)
|
||||
return context
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
def form_valid(self, form):
|
||||
if self.can_delete(self.get_object()):
|
||||
return super().delete(request, *args, **kwargs)
|
||||
return super().form_valid(form)
|
||||
else:
|
||||
messages.error(request, self.cannot_delete_message)
|
||||
return super().get(request)
|
||||
messages.error(self.request, self.cannot_delete_message)
|
||||
return super().get(self.request)
|
||||
|
||||
|
||||
class LocaleViewSet(ModelViewSet):
|
||||
|
|
Ładowanie…
Reference in New Issue