Add support for single or multiple objects modes
View that use the MultipleObjectMixin can now fully operate as single object or multiple object views. Add the self.view_mode_single and self.view_mode_multiple flags. Add support for single, singular and plural titles and success messages via: success_message_single, success_message_singular, sucess_message_plural, title_single, title_singular and title_plural class attributes. Insert object_list and object as attributes of the view class to avoid calling the queryset again. Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -251,32 +251,6 @@ class MultipleObjectDownloadView(RestrictedQuerysetMixin, MultipleObjectMixin, D
|
||||
return super(MultipleObjectDownloadView, self).get_queryset()
|
||||
|
||||
|
||||
class SingleObjectDownloadView(RestrictedQuerysetMixin, SingleObjectMixin, DownloadViewBase):
|
||||
"""
|
||||
View that provides a .get_object() method to download content from a
|
||||
single object.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
result = super(SingleObjectDownloadView, self).__init__(*args, **kwargs)
|
||||
|
||||
if self.__class__.mro()[0].get_queryset != SingleObjectDownloadView.get_queryset:
|
||||
raise ImproperlyConfigured(
|
||||
'%(cls)s is overloading the get_queryset method. Subclasses '
|
||||
'should implement the get_source_queryset method instead. ' % {
|
||||
'cls': self.__class__.__name__
|
||||
}
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
return super(SingleObjectDownloadView, self).get_queryset()
|
||||
except ImproperlyConfigured:
|
||||
self.queryset = self.get_source_queryset()
|
||||
return super(SingleObjectDownloadView, self).get_queryset()
|
||||
|
||||
|
||||
class MultiFormView(DjangoFormView):
|
||||
prefix = None
|
||||
prefixes = {}
|
||||
@@ -607,7 +581,7 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM
|
||||
)
|
||||
|
||||
|
||||
class MultipleObjectFormActionView(ObjectActionMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin, MultipleObjectMixin, FormExtraKwargsMixin, ExtraContextMixin, RedirectionMixin, DjangoFormView):
|
||||
class MultipleObjectFormActionView(ExtraContextMixin, ObjectActionMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin, MultipleObjectMixin, FormExtraKwargsMixin, RedirectionMixin, DjangoFormView):
|
||||
"""
|
||||
This view will present a form and upon receiving a POST request will
|
||||
perform an action on an object or queryset
|
||||
@@ -639,7 +613,7 @@ class MultipleObjectFormActionView(ObjectActionMixin, ViewPermissionCheckMixin,
|
||||
return super(MultipleObjectFormActionView, self).get_queryset()
|
||||
|
||||
|
||||
class MultipleObjectConfirmActionView(ObjectActionMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin, MultipleObjectMixin, ExtraContextMixin, RedirectionMixin, TemplateView):
|
||||
class MultipleObjectConfirmActionView(ExtraContextMixin, ObjectActionMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin, MultipleObjectMixin, RedirectionMixin, TemplateView):
|
||||
template_name = 'appearance/generic_confirm.html'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -738,6 +712,32 @@ class SingleObjectCreateView(ObjectNameMixin, ViewPermissionCheckMixin, ExtraCon
|
||||
return self.error_message_duplicate
|
||||
|
||||
|
||||
class SingleObjectDownloadView(RestrictedQuerysetMixin, SingleObjectMixin, DownloadViewBase):
|
||||
"""
|
||||
View that provides a .get_object() method to download content from a
|
||||
single object.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
result = super(SingleObjectDownloadView, self).__init__(*args, **kwargs)
|
||||
|
||||
if self.__class__.mro()[0].get_queryset != SingleObjectDownloadView.get_queryset:
|
||||
raise ImproperlyConfigured(
|
||||
'%(cls)s is overloading the get_queryset method. Subclasses '
|
||||
'should implement the get_source_queryset method instead. ' % {
|
||||
'cls': self.__class__.__name__
|
||||
}
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
return super(SingleObjectDownloadView, self).get_queryset()
|
||||
except ImproperlyConfigured:
|
||||
self.queryset = self.get_source_queryset()
|
||||
return super(SingleObjectDownloadView, self).get_queryset()
|
||||
|
||||
|
||||
class SingleObjectDynamicFormCreateView(DynamicFormViewMixin, SingleObjectCreateView):
|
||||
pass
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ class MultipleInstanceActionMixin(object):
|
||||
# MultipleObjectFormActionView or MultipleObjectConfirmActionView
|
||||
|
||||
model = None
|
||||
success_message = _('Operation performed on %(count)d object')
|
||||
success_message_singular = _('Operation performed on %(count)d object')
|
||||
success_message_plural = _('Operation performed on %(count)d objects')
|
||||
|
||||
def get_pk_list(self):
|
||||
@@ -217,6 +217,13 @@ class MultipleObjectMixin(SingleObjectMixin):
|
||||
pk_list_key = 'id_list'
|
||||
pk_list_separator = PK_LIST_SEPARATOR
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object_list = self.get_object_list()
|
||||
if self.view_mode_single:
|
||||
self.object = self.object_list.first()
|
||||
|
||||
return super(MultipleObjectMixin, self).dispatch(request=request, *args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
Override BaseDetailView.get()
|
||||
@@ -243,6 +250,9 @@ class MultipleObjectMixin(SingleObjectMixin):
|
||||
`pk_list' argument in the URLconf, but subclasses can override this
|
||||
to return any object.
|
||||
"""
|
||||
self.view_mode_single = False
|
||||
self.view_mode_multiple = False
|
||||
|
||||
# Use a custom queryset if provided; this is required for subclasses
|
||||
# like DateDetailView
|
||||
if queryset is None:
|
||||
@@ -255,14 +265,17 @@ class MultipleObjectMixin(SingleObjectMixin):
|
||||
|
||||
if pk is not None:
|
||||
queryset = queryset.filter(pk=pk)
|
||||
self.view_mode_single = True
|
||||
|
||||
# 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})
|
||||
self.view_mode_single = True
|
||||
|
||||
if pk_list is not None:
|
||||
queryset = queryset.filter(pk__in=self.get_pk_list())
|
||||
self.view_mode_multiple = True
|
||||
|
||||
# If none of those are defined, it's an error.
|
||||
if pk is None and slug is None and pk_list is None:
|
||||
@@ -305,22 +318,49 @@ class ObjectActionMixin(object):
|
||||
"""
|
||||
Mixin that performs an user action to a queryset
|
||||
"""
|
||||
error_message = 'Unable to perform operation on object %(instance)s.'
|
||||
error_message = 'Unable to perform operation on object %(instance)s; %(exception)s.'
|
||||
post_object_action_url = None
|
||||
success_message = 'Operation performed on %(count)d object.'
|
||||
success_message_single = 'Operation performed on %(object)s.'
|
||||
success_message_singular = 'Operation performed on %(count)d object.'
|
||||
success_message_plural = 'Operation performed on %(count)d objects.'
|
||||
title_single = 'Perform operation on %(object)s.'
|
||||
title_singular = 'Perform operation on %(count)d object.'
|
||||
title_plural = 'Perform operation on %(count)d objects.'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ObjectActionMixin, self).get_context_data(**kwargs)
|
||||
title = None
|
||||
|
||||
if self.view_mode_single:
|
||||
title = self.title_single % {'object': self.object}
|
||||
elif self.view_mode_multiple:
|
||||
title = ungettext(
|
||||
singular=self.title_singular,
|
||||
plural=self.title_plural,
|
||||
number=self.object_list.count()
|
||||
) % {
|
||||
'count': self.object_list.count(),
|
||||
}
|
||||
|
||||
context['title'] = title
|
||||
|
||||
return context
|
||||
|
||||
def get_post_object_action_url(self):
|
||||
return self.post_object_action_url
|
||||
|
||||
def get_success_message(self, count):
|
||||
return ungettext(
|
||||
singular=self.success_message,
|
||||
plural=self.success_message_plural,
|
||||
number=count
|
||||
) % {
|
||||
'count': count,
|
||||
}
|
||||
if self.view_mode_single:
|
||||
return self.success_message_single % {'object': self.object}
|
||||
|
||||
if self.view_mode_multiple:
|
||||
return ungettext(
|
||||
singular=self.success_message_singular,
|
||||
plural=self.success_message_plural,
|
||||
number=count
|
||||
) % {
|
||||
'count': count,
|
||||
}
|
||||
|
||||
def object_action(self, instance, form=None):
|
||||
# User supplied method
|
||||
@@ -330,7 +370,7 @@ class ObjectActionMixin(object):
|
||||
self.action_count = 0
|
||||
self.action_id_list = []
|
||||
|
||||
for instance in self.get_object_list():
|
||||
for instance in self.object_list:
|
||||
try:
|
||||
self.object_action(form=form, instance=instance)
|
||||
except Exception as exception:
|
||||
|
||||
Reference in New Issue
Block a user