Refacto ActionView into MultipleObjectFormActionView and MultipleObjectConfirmActionView.
Split ActionView into smaller mixins.
This commit is contained in:
@@ -3,9 +3,8 @@ from __future__ import absolute_import, unicode_literals
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import (
|
||||
FormView as DjangoFormView, DetailView, TemplateView
|
||||
)
|
||||
@@ -18,121 +17,38 @@ from django.views.generic.list import ListView
|
||||
from django_downloadview import VirtualDownloadView, VirtualFile
|
||||
from pure_pagination.mixins import PaginationMixin
|
||||
|
||||
from acls.models import AccessControlList
|
||||
|
||||
from .forms import ChoiceForm
|
||||
from .mixins import * # NOQA
|
||||
from .settings import setting_paginate_by
|
||||
|
||||
__all__ = (
|
||||
'ActionView', 'AssignRemoveView', 'ConfirmView', 'FormView',
|
||||
'MultiFormView', 'SingleObjectCreateView', 'SingleObjectDeleteView',
|
||||
'AssignRemoveView', 'ConfirmView', 'FormView', 'MultiFormView',
|
||||
'MultipleObjectConfirmActionView', 'MultipleObjectFormActionView',
|
||||
'SingleObjectCreateView', 'SingleObjectDeleteView',
|
||||
'SingleObjectDetailView', 'SingleObjectEditView', 'SingleObjectListView',
|
||||
'SimpleView',
|
||||
'SimpleView'
|
||||
)
|
||||
|
||||
|
||||
class ActionView(ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, DjangoFormView):
|
||||
class MultipleObjectFormActionView(ObjectActionMixin, MultipleObjectMixin, FormExtraKwargsMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, DjangoFormView):
|
||||
"""
|
||||
This view will present a form and upon receiving a POST request will
|
||||
perform an action on an object or queryset
|
||||
"""
|
||||
|
||||
queryset = None
|
||||
model = None
|
||||
pk_url_kwarg = 'pk'
|
||||
object_permission = None
|
||||
slug_url_kwarg = 'slug'
|
||||
success_message = 'Operation performed on %(count)d object'
|
||||
success_message_plural = 'Operation performed on %(count)d objects'
|
||||
template_name = 'appearance/generic_form.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
self.view_action(form=form)
|
||||
return super(ActionView, self).form_valid(form=form)
|
||||
return super(MultipleObjectFormActionView, self).form_valid(form=form)
|
||||
|
||||
def get_form_extra_kwargs(self):
|
||||
return {}
|
||||
|
||||
def get_form_kwargs(self):
|
||||
result = super(ActionView, self).get_form_kwargs()
|
||||
result.update(self.get_form_extra_kwargs())
|
||||
return result
|
||||
class MultipleObjectConfirmActionView(ObjectActionMixin, MultipleObjectMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, TemplateView):
|
||||
template_name = 'appearance/generic_confirm.html'
|
||||
|
||||
def get_pk_list(self):
|
||||
result = self.request.GET.get(
|
||||
'id_list', self.request.POST.get('id_list')
|
||||
)
|
||||
|
||||
if result:
|
||||
return result.split(',')
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_queryset(self):
|
||||
if self.queryset is not None:
|
||||
queryset = self.queryset
|
||||
if isinstance(queryset, QuerySet):
|
||||
queryset = queryset.all()
|
||||
elif self.model is not None:
|
||||
queryset = self.model._default_manager.all()
|
||||
|
||||
pk = self.kwargs.get(self.pk_url_kwarg)
|
||||
slug = self.kwargs.get(self.slug_url_kwarg)
|
||||
pk_list = self.get_pk_list()
|
||||
|
||||
if pk is not None:
|
||||
queryset = queryset.filter(pk=pk)
|
||||
|
||||
# Next, try looking up by slug.
|
||||
if slug is not None and (pk is None or self.query_pk_and_slug):
|
||||
slug_field = self.get_slug_field()
|
||||
queryset = queryset.filter(**{slug_field: slug})
|
||||
|
||||
if pk_list is not None:
|
||||
queryset = queryset.filter(pk__in=self.get_pk_list())
|
||||
|
||||
if pk is None and slug is None and pk_list is None:
|
||||
raise AttributeError(
|
||||
'Generic detail view %s must be called with '
|
||||
'either an object pk, a slug or an id list.'
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
if self.object_permission:
|
||||
return AccessControlList.objects.filter_by_access(
|
||||
self.object_permission, self.request.user, queryset=queryset
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
||||
def get_success_message(self, count):
|
||||
return ungettext(
|
||||
self.success_message,
|
||||
self.success_message_plural,
|
||||
count
|
||||
) % {
|
||||
'count': count,
|
||||
}
|
||||
|
||||
def object_action(self, form, instance):
|
||||
pass
|
||||
|
||||
def view_action(self, form):
|
||||
count = 0
|
||||
|
||||
for instance in self.get_queryset():
|
||||
try:
|
||||
self.object_action(form=form, instance=instance)
|
||||
except PermissionDenied:
|
||||
pass
|
||||
else:
|
||||
count += 1
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
self.get_success_message(count=count)
|
||||
)
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.view_action()
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
||||
class AssignRemoveView(ExtraContextMixin, ViewPermissionCheckMixin, ObjectPermissionCheckMixin, TemplateView):
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models.query import QuerySet
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
|
||||
from permissions import Permission
|
||||
|
||||
from acls.models import AccessControlList
|
||||
|
||||
|
||||
__all__ = (
|
||||
'DeleteExtraDataMixin', 'ExtraContextMixin',
|
||||
'DeleteExtraDataMixin', 'ExtraContextMixin', 'FormExtraKwargsMixin',
|
||||
'MultipleObjectMixin', 'ObjectActionMixin',
|
||||
'ObjectListPermissionFilterMixin', 'ObjectNameMixin',
|
||||
'ObjectPermissionCheckMixin', 'RedirectionMixin',
|
||||
'ViewPermissionCheckMixin'
|
||||
@@ -30,7 +34,27 @@ class DeleteExtraDataMixin(object):
|
||||
return HttpResponseRedirect(success_url)
|
||||
|
||||
|
||||
class FormExtraKwargsMixin(object):
|
||||
"""
|
||||
Mixin that allows a view to pass extra keyword arguments to forms
|
||||
"""
|
||||
|
||||
form_extra_kwargs = {}
|
||||
|
||||
def get_form_extra_kwargs(self):
|
||||
return self.form_extra_kwargs
|
||||
|
||||
def get_form_kwargs(self):
|
||||
result = super(FormExtraKwargsMixin, self).get_form_kwargs()
|
||||
result.update(self.get_form_extra_kwargs())
|
||||
return result
|
||||
|
||||
|
||||
class ExtraContextMixin(object):
|
||||
"""
|
||||
Mixin that allows views to pass extra context to the template
|
||||
"""
|
||||
|
||||
extra_context = {}
|
||||
|
||||
def get_extra_context(self):
|
||||
@@ -44,8 +68,8 @@ class ExtraContextMixin(object):
|
||||
|
||||
class MultipleInstanceActionMixin(object):
|
||||
model = None
|
||||
success_message = 'Operation performed on %(count)d object'
|
||||
success_message_plural = 'Operation performed on %(count)d objects'
|
||||
success_message = _('Operation performed on %(count)d object')
|
||||
success_message_plural = _('Operation performed on %(count)d objects')
|
||||
|
||||
def get_pk_list(self):
|
||||
return self.request.GET.get(
|
||||
@@ -82,14 +106,108 @@ class MultipleInstanceActionMixin(object):
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
||||
class MultipleObjectMixin(object):
|
||||
"""
|
||||
Mixin that allows a view to work on a single or multiple objects
|
||||
"""
|
||||
|
||||
model = None
|
||||
object_permission = None
|
||||
pk_list_key = 'id_list'
|
||||
pk_list_separator = ','
|
||||
pk_url_kwarg = 'pk'
|
||||
queryset = None
|
||||
slug_url_kwarg = 'slug'
|
||||
|
||||
def get_pk_list(self):
|
||||
result = self.request.GET.get(
|
||||
self.pk_list_key, self.request.POST.get(self.pk_list_key)
|
||||
)
|
||||
|
||||
if result:
|
||||
return result.split(self.pk_list_separator)
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_queryset(self):
|
||||
if self.queryset is not None:
|
||||
queryset = self.queryset
|
||||
if isinstance(queryset, QuerySet):
|
||||
queryset = queryset.all()
|
||||
elif self.model is not None:
|
||||
queryset = self.model._default_manager.all()
|
||||
|
||||
pk = self.kwargs.get(self.pk_url_kwarg)
|
||||
slug = self.kwargs.get(self.slug_url_kwarg)
|
||||
pk_list = self.get_pk_list()
|
||||
|
||||
if pk is not None:
|
||||
queryset = queryset.filter(pk=pk)
|
||||
|
||||
# Next, try looking up by slug.
|
||||
if slug is not None and (pk is None or self.query_pk_and_slug):
|
||||
slug_field = self.get_slug_field()
|
||||
queryset = queryset.filter(**{slug_field: slug})
|
||||
|
||||
if pk_list is not None:
|
||||
queryset = queryset.filter(pk__in=self.get_pk_list())
|
||||
|
||||
if pk is None and slug is None and pk_list is None:
|
||||
raise AttributeError(
|
||||
'Generic detail view %s must be called with '
|
||||
'either an object pk, a slug or an id list.'
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
if self.object_permission:
|
||||
return AccessControlList.objects.filter_by_access(
|
||||
self.object_permission, self.request.user, queryset=queryset
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
||||
|
||||
class ObjectActionMixin(object):
|
||||
"""
|
||||
Mixin that performs an user action to a queryset
|
||||
"""
|
||||
|
||||
success_message = 'Operation performed on %(count)d object'
|
||||
success_message_plural = 'Operation performed on %(count)d objects'
|
||||
|
||||
def get_success_message(self, count):
|
||||
return ungettext(
|
||||
self.success_message,
|
||||
self.success_message_plural,
|
||||
count
|
||||
) % {
|
||||
'count': count,
|
||||
}
|
||||
|
||||
def object_action(self, instance, form=None):
|
||||
pass
|
||||
|
||||
def view_action(self, form=None):
|
||||
count = 0
|
||||
|
||||
for instance in self.get_queryset():
|
||||
try:
|
||||
self.object_action(form=form, instance=instance)
|
||||
except PermissionDenied:
|
||||
pass
|
||||
else:
|
||||
count += 1
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
self.get_success_message(count=count)
|
||||
)
|
||||
|
||||
|
||||
class ObjectListPermissionFilterMixin(object):
|
||||
object_permission = None
|
||||
|
||||
def get_queryset(self):
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
queryset = super(ObjectListPermissionFilterMixin, self).get_queryset()
|
||||
|
||||
if self.object_permission:
|
||||
@@ -123,10 +241,6 @@ class ObjectPermissionCheckMixin(object):
|
||||
return self.get_object()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
if self.object_permission:
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=self.object_permission, user=request.user,
|
||||
|
||||
Reference in New Issue
Block a user