1
# Copyright 2012 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
6
from __future__ import (
19
"settings_add_archive",
27
from django.contrib import messages
28
from django.http import (
32
from django.views.generic import DeleteView
35
class HelpfulDeleteView(DeleteView):
36
"""Extension to Django's :class:`django.views.generic.DeleteView`.
38
This modifies `DeleteView` in a few ways:
39
- Deleting a nonexistent object is considered successful.
40
- There's a callback that lets you describe the object to the user.
41
- User feedback is built in.
42
- get_success_url defaults to returning the "next" URL.
43
- Confirmation screen also deals nicely with already-deleted object.
45
:ivar model: The model class this view is meant to delete.
48
__metaclass__ = ABCMeta
52
"""Retrieve the object to be deleted."""
55
def get_next_url(self):
56
"""URL of page to proceed to after deleting."""
58
def delete(self, *args, **kwargs):
59
"""Delete result of self.get_object(), if any."""
61
self.object = self.get_object()
63
feedback = self.compose_feedback_nonexistent()
66
feedback = self.compose_feedback_deleted(self.object)
67
return self.move_on(feedback)
69
def get(self, *args, **kwargs):
70
"""Prompt for confirmation of deletion request in the UI.
72
This is where the view acts as a regular template view.
74
If the object has been deleted in the meantime though, don't bother:
75
we'll just redirect to the next URL and show a notice that the object
79
return super(HelpfulDeleteView, self).get(*args, **kwargs)
81
return self.move_on(self.compose_feedback_nonexistent())
83
def compose_feedback_nonexistent(self):
84
"""Compose feedback message: "obj was already deleted"."""
85
return "Not deleting: %s not found." % self.model._meta.verbose_name
87
def compose_feedback_deleted(self, obj):
88
"""Compose feedback message: "obj has been deleted"."""
89
return ("%s deleted." % self.name_object(obj)).capitalize()
91
def name_object(self, obj):
92
"""Overridable: describe object being deleted to the user.
94
The result text will be included in a user notice along the lines of
97
:param obj: Object that's been deleted from the database.
98
:return: Description of the object, along the lines of
99
"User <obj.username>".
101
return obj._meta.verbose_name
103
def show_notice(self, notice):
104
"""Wrapper for messages.info."""
105
messages.info(self.request, notice)
107
def move_on(self, feedback_message):
108
"""Redirect to the post-deletion page, showing the given message."""
109
self.show_notice(feedback_message)
110
return HttpResponseRedirect(self.get_next_url())
113
def process_form(request, form_class, redirect_url, prefix,
114
success_message=None, form_kwargs=None):
115
"""Utility method to process subforms (i.e. forms with a prefix).
117
:param request: The request which contains the data to be validated.
118
:type request: django.http.HttpRequest
119
:param form_class: The form class used to perform the validation.
120
:type form_class: django.forms.Form
121
:param redirect_url: The url where the user should be redirected if the
122
form validates successfully.
123
:type redirect_url: basestring
124
:param prefix: The prefix of the form.
125
:type prefix: basestring
126
:param success_message: An optional message that will be displayed if the
127
form validates successfully.
128
:type success_message: basestring
129
:param form_kwargs: An optional dict that will passed to the form creation
131
:type form_kwargs: dict or None
132
:return: A tuple of the validated form and a response (the response will
133
not be None only if the form has been validated correctly).
137
if form_kwargs is None:
139
if '%s_submit' % prefix in request.POST:
141
data=request.POST, prefix=prefix, **form_kwargs)
143
if success_message is not None:
144
messages.info(request, success_message)
146
return form, HttpResponseRedirect(redirect_url)
148
form = form_class(prefix=prefix, **form_kwargs)