Source code for djcrud.views.list_action
import functools
from django.forms import Form
from ..model import ModelMixin
from .. import tags
from .action import ActionMixin, ObjectListPermissionMixin
from .form import FormMixin, FormView
[docs]
class ListActionMixin(ModelMixin, FormMixin, ObjectListPermissionMixin):
"""Bulk actions from the list action bar (selected row PKs in ``pks``).
Brings in :class:`~djcrud.views.action.ObjectListPermissionMixin` so that
when combined with :class:`~djcrud.views.action.ActionMixin` (as
:class:`ListActionView` does), per-target permission checks (general
shortcode + :meth:`~djcrud.views.action.ActionMixin.has_permission_object`
per row) are performed against each row in ``self.object_list``.
The bar itself lists *configured* LIST_ACTION routes (see
:attr:`~djcrud.views.list.ListMixin.list_actions`, which walks tagged
routes directly with no permission check). Per-object allowance (always
checked with a concrete object) is propagated via ``data-list-actions``
on checkboxes and filtered client-side.
Attributes:
tags (list[str]): Must include ``djcrud.tags.LIST_ACTION`` for discovery.
title (str): Action label in the list action bar.
icon (str): Bootstrap Icons name.
color (str): Bulma button colour modifier.
message (str): Confirmation text in the action modal.
form_class (type): Form class for the action. Default empty ``Form``.
"""
tags = [tags.LIST_ACTION] # see djcrud.tags.LIST_ACTION
[docs]
def get_queryset(self):
"""Scoped queryset from the enclosing router."""
return super().get_queryset()
@functools.cached_property
def pks(self):
"""Selected primary keys from GET or POST."""
return self.request.GET.getlist("pks") or self.request.POST.getlist("pks")
@functools.cached_property
def object_list(self):
"""Intersection of :attr:`pks` with the scoped queryset."""
return self.get_queryset().filter(pk__in=self.pks)
@functools.cached_property
def invalid_pks(self):
"""Count of PKs outside the scoped queryset."""
return len(self.pks) - self.object_list.count()
[docs]
def get_success_url(self):
"""Redirect back to the list view after the action."""
list_route = self.router.find_route("list")
return type(list_route)(request=self.request).url
@property
def form_attributes(self):
"""Form tag attributes including list-action selection cleanup."""
attrs = dict(FormMixin.form_attributes)
attrs["up-on-finished"] = "djcrudClearListActionSelections()"
return attrs
def unpoly_attributes(self, context=""):
attrs = super().unpoly_attributes(context)
if context == "list_action_bar":
attrs["data-list-action"] = "urlupdate"
attrs["up-on-accepted"] = (
"djcrudClearListActionSelections(); up.visit(response.url)"
)
return attrs
[docs]
class ListActionView(ListActionMixin, ActionMixin, FormView):
"""Bulk action form opened from the list action bar.
Includes :class:`~djcrud.views.action.ActionMixin` + :class:`~djcrud.views.action.ObjectListPermissionMixin`
(via the mixin) so per-target permission checks are performed uniformly.
Override :meth:`~djcrud.views.action.ActionMixin.has_permission_object` for
extra per-row rules after the registry check.
"""
pass