mirror of
https://github.com/jazzband/django-admin2.git
synced 2026-05-03 13:04:46 +00:00
For #161, this removes the FBV and implements an easily extendible BaseListAction class
This commit is contained in:
parent
1916f7cba4
commit
0da6f453b7
5 changed files with 85 additions and 55 deletions
|
|
@ -14,7 +14,7 @@ def get_description(action):
|
|||
return capfirst(action.__name__.replace('_', ' '))
|
||||
|
||||
|
||||
def delete_selected(request, queryset):
|
||||
class BaseListAction(object):
|
||||
# We check whether the user has permission to delete the objects in the
|
||||
# queryset.
|
||||
#
|
||||
|
|
@ -25,52 +25,71 @@ def delete_selected(request, queryset):
|
|||
# `get_deleted_objects` in contrib.admin.util for how this is currently
|
||||
# done. (Hint: I think we can do better.)
|
||||
|
||||
model = queryset.model
|
||||
opts = utils.model_options(model)
|
||||
permission_name = '%s.delete.%s' \
|
||||
% (opts.app_label, opts.object_name.lower())
|
||||
has_permission = request.user.has_perm(permission_name)
|
||||
|
||||
if len(queryset) == 1:
|
||||
objects_name = opts.verbose_name
|
||||
else:
|
||||
objects_name = opts.verbose_name_plural
|
||||
objects_name = unicode(objects_name)
|
||||
|
||||
if request.POST.get('confirmed'):
|
||||
# The user has confirmed that they want to delete the objects.
|
||||
if has_permission:
|
||||
num_objects_deleted = len(queryset)
|
||||
queryset.delete()
|
||||
message = "Successfully deleted %d %s" % \
|
||||
(num_objects_deleted, objects_name)
|
||||
messages.add_message(request, messages.INFO, message)
|
||||
return None
|
||||
def __init__(self, request, queryset):
|
||||
self.request = request
|
||||
self.queryset = queryset
|
||||
self.model = queryset.model
|
||||
self.options = utils.model_options(self.model)
|
||||
self.permission_name = '%s.delete.%s' \
|
||||
% (self.options.app_label, self.options.object_name.lower())
|
||||
self.has_permission = request.user.has_perm(self.permission_name)
|
||||
if queryset.count() == 1:
|
||||
objects_name = self.options.verbose_name
|
||||
else:
|
||||
raise PermissionDenied
|
||||
else:
|
||||
# The user has not confirmed that they want to delete the objects, so
|
||||
# render a template asking for their confirmation.
|
||||
if has_permission:
|
||||
template = 'admin2/bootstrap/delete_selected_confirmation.html'
|
||||
objects_name = self.options.verbose_name_plural
|
||||
self.objects_name = unicode(objects_name)
|
||||
|
||||
def _format_callback(obj):
|
||||
opts = utils.model_options(obj)
|
||||
return '%s: %s' % (force_text(capfirst(opts.verbose_name)),
|
||||
force_text(obj))
|
||||
def description(self):
|
||||
return NotImplemented
|
||||
|
||||
collector = utils.NestedObjects(using=None)
|
||||
collector.collect(queryset)
|
||||
def get_response(self):
|
||||
return NotImplemented
|
||||
|
||||
context = {
|
||||
'queryset': queryset,
|
||||
'objects_name': objects_name,
|
||||
'deletable_objects': collector.nested(_format_callback),
|
||||
}
|
||||
return TemplateResponse(request, template, context)
|
||||
def get_template(self):
|
||||
return NotImplemented
|
||||
|
||||
def __call__(self):
|
||||
return self.get_response()
|
||||
|
||||
|
||||
class DeleteSelectedAction(BaseListAction):
|
||||
|
||||
description = "Delete selected items"
|
||||
|
||||
def get_response(self):
|
||||
if self.request.POST.get('confirmed'):
|
||||
# The user has confirmed that they want to delete the objects.
|
||||
if self.has_permission:
|
||||
num_objects_deleted = len(self.queryset)
|
||||
self.queryset.delete()
|
||||
message = "Successfully deleted %d %s" % \
|
||||
(num_objects_deleted, self.objects_name)
|
||||
messages.add_message(self.request, messages.INFO, message)
|
||||
return None
|
||||
else:
|
||||
raise PermissionDenied
|
||||
else:
|
||||
message = "Permission to delete %s denied" % objects_name
|
||||
messages.add_message(request, messages.INFO, message)
|
||||
return None
|
||||
# The user has not confirmed that they want to delete the objects, so
|
||||
# render a template asking for their confirmation.
|
||||
if self.has_permission:
|
||||
template = 'admin2/bootstrap/actions/delete_selected_confirmation.html'
|
||||
|
||||
def _format_callback(obj):
|
||||
opts = utils.model_options(obj)
|
||||
return '%s: %s' % (force_text(capfirst(opts.verbose_name)),
|
||||
force_text(obj))
|
||||
|
||||
collector = utils.NestedObjects(using=None)
|
||||
collector.collect(self.queryset)
|
||||
|
||||
context = {
|
||||
'queryset': self.queryset,
|
||||
'objects_name': self.objects_name,
|
||||
'deletable_objects': collector.nested(_format_callback),
|
||||
}
|
||||
return TemplateResponse(self.request, template, context)
|
||||
else:
|
||||
message = "Permission to delete %s denied" % self.objects_name
|
||||
messages.add_message(self.request, messages.INFO, message)
|
||||
return None
|
||||
|
||||
delete_selected.description = "Delete selected items"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="confirmed" value="yes" />
|
||||
<input type="hidden" name="action" value="delete_selected" />
|
||||
<input type="hidden" name="action" value="DeleteSelectedAction" />
|
||||
{% for item in queryset %}
|
||||
<input type="hidden" name="selected_model_pk" value="{{ item.pk }}" />
|
||||
{% endfor %}
|
||||
|
|
@ -45,7 +45,7 @@ class ModelAdmin2(object):
|
|||
list_fields = []
|
||||
|
||||
#This shows up on the DocumentListView of the Posts
|
||||
list_actions = [actions.delete_selected]
|
||||
list_actions = [actions.DeleteSelectedAction]
|
||||
|
||||
# This shows up in the DocumentDetailView of the Posts.
|
||||
document_actions = []
|
||||
|
|
@ -220,7 +220,7 @@ class ModelAdmin2(object):
|
|||
actions_dict[action.__name__] = {
|
||||
'name': action.__name__,
|
||||
'description': actions.get_description(action),
|
||||
'func': action
|
||||
'action_class': action
|
||||
}
|
||||
return actions_dict
|
||||
|
||||
|
|
|
|||
|
|
@ -52,13 +52,24 @@ class ModelListView(AdminModel2Mixin, generic.ListView):
|
|||
permissions.IsStaffPermission,
|
||||
permissions.ModelViewPermission)
|
||||
|
||||
# def post(self, request):
|
||||
# # This is where we handle actions
|
||||
# action_name = request.POST['action']
|
||||
# action_func = self.get_actions()[action_name]['func']
|
||||
# selected_model_pks = request.POST.getlist('selected_model_pk')
|
||||
# queryset = self.model.objects.filter(pk__in=selected_model_pks)
|
||||
# response = action_func(request, queryset)
|
||||
# if response is None:
|
||||
# return HttpResponseRedirect(self.get_success_url())
|
||||
# else:
|
||||
# return response
|
||||
|
||||
def post(self, request):
|
||||
# This is where we handle actions
|
||||
action_name = request.POST['action']
|
||||
action_func = self.get_actions()[action_name]['func']
|
||||
action_class = self.get_actions()[action_name]['action_class']
|
||||
selected_model_pks = request.POST.getlist('selected_model_pk')
|
||||
queryset = self.model.objects.filter(pk__in=selected_model_pks)
|
||||
response = action_func(request, queryset)
|
||||
response = action_class(request, queryset)()
|
||||
if response is None:
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -32,17 +32,17 @@ class PostListTest(BaseIntegrationTest):
|
|||
|
||||
def test_actions_displayed(self):
|
||||
response = self.client.get(reverse("admin2:blog_post_index"))
|
||||
self.assertInHTML('<option value="delete_selected">Delete selected items</option>', response.content)
|
||||
self.assertInHTML('<option value="DeleteSelectedAction">Delete selected items</option>', response.content)
|
||||
|
||||
def test_delete_selected_post(self):
|
||||
post = Post.objects.create(title="a_post_title", body="body")
|
||||
params = {'action': 'delete_selected', 'selected_model_pk': str(post.pk)}
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(post.pk)}
|
||||
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
||||
self.assertInHTML('<p>Are you sure you want to delete the selected post? All of the following items will be deleted:</p>', response.content)
|
||||
|
||||
def test_delete_selected_post_confirmation(self):
|
||||
post = Post.objects.create(title="a_post_title", body="body")
|
||||
params = {'action': 'delete_selected', 'selected_model_pk': str(post.pk), 'confirmed': 'yes'}
|
||||
params = {'action': 'DeleteSelectedAction', 'selected_model_pk': str(post.pk), 'confirmed': 'yes'}
|
||||
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
||||
self.assertRedirects(response, reverse("admin2:blog_post_index"))
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ class PostDeleteActionTest(BaseIntegrationTest):
|
|||
p1 = Post.objects.create(title="A Post Title", body="body")
|
||||
p2 = Post.objects.create(title="A Post Title", body="body")
|
||||
post_data = {
|
||||
'action': 'delete_selected',
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [p1.pk, p2.pk]
|
||||
}
|
||||
response = self.client.post(reverse("admin2:blog_post_index"),
|
||||
|
|
@ -152,7 +152,7 @@ class PostDeleteActionTest(BaseIntegrationTest):
|
|||
p1 = Post.objects.create(title="A Post Title", body="body")
|
||||
p2 = Post.objects.create(title="A Post Title", body="body")
|
||||
post_data = {
|
||||
'action': 'delete_selected',
|
||||
'action': 'DeleteSelectedAction',
|
||||
'selected_model_pk': [p1.pk, p2.pk],
|
||||
'confirmed': 'yes'
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue