PK ! inline_actions/__init__.pyPK ! 3K K inline_actions/__init__.py.orig<<<<<<< HEAD __version__ = '2.1.0' ======= >>>>>>> build: switch to poetry PK ! : inline_actions/actions.pyfrom django.contrib import messages from django.shortcuts import redirect from django.urls import reverse from django.utils.translation import ugettext_lazy as _ class ViewAction: inline_actions = ['view_action'] def view_action(self, request, obj, parent_obj=None): """Redirect to changeform of selcted inline instance""" url = reverse( 'admin:{}_{}_change'.format( obj._meta.app_label, obj._meta.model_name, ), args=(obj.pk,) ) return redirect(url) view_action.short_description = _("View") class DeleteAction: def get_inline_actions(self, request, obj=None): actions = super().get_inline_actions(request, obj) if self.has_delete_permission(request, obj): actions.append('delete_action') return actions def delete_action(self, request, obj, parent_obj=None): """Remove selected inline instance if permission is sufficient""" if self.has_delete_permission(request): obj.delete() messages.info(request, "`{}` deleted.".format(obj)) delete_action.short_description = _("Delete") class DefaultActionsMixin(ViewAction, DeleteAction): inline_actions = [] PK ! ;-( ( inline_actions/admin.pyfrom django.apps import apps from django.contrib import admin from django.http import HttpResponse from django.shortcuts import redirect from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.text import capfirst from django.utils.translation import ugettext_lazy as _ class InlineActionException(Exception): pass class ActionNotCallable(InlineActionException): def __init__(self, model_admin, action, *args, **kwargs): super().__init__(*args, **kwargs) self.model_admin = model_admin self.action = action class BaseInlineActionsMixin: INLINE_MODEL_ADMIN = 'inline' MODEL_ADMIN = 'admin' inline_actions = [] def get_inline_actions(self, request, obj=None): """ Returns a list of all actions for this Admin. """ # If self.actions is explicitly set to None that means that we don't # want *any* actions enabled on this page. if self.inline_actions is None: return [] actions = [] # Gather actions from the inline admin and all parent classes, # starting with self and working back up. for klass in self.__class__.mro()[::-1]: class_actions = getattr(klass, 'inline_actions', []) # Avoid trying to iterate over None if not class_actions: continue for action in class_actions: if action not in actions: actions.append(action) return actions def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) fields = list(fields) if 'render_inline_actions' not in fields: fields.append('render_inline_actions') return fields def _get_admin_type(self, model_admin=None): """ Returns wether this is an InlineAdmin or not. """ model_admin = model_admin or self if isinstance(model_admin, admin.options.InlineModelAdmin): return self.INLINE_MODEL_ADMIN return self.MODEL_ADMIN def render_inline_actions(self, obj=None): # NOQA: C901 """ Renders all defined inline actions as html. """ if not (obj and obj.pk): return '' buttons = [] for action_name in self.get_inline_actions(self._request, obj): action_func = getattr(self, action_name, None) if not action_func: raise RuntimeError( "Could not find action `{}`".format(action_name)) # Add per-object label support action_name = action_func.__name__ label_handler = getattr( self, 'get_{}_label'.format(action_name), None) if callable(label_handler): description = label_handler(obj=obj) else: try: description = action_func.short_description except AttributeError: description = capfirst(action_name.replace('_', ' ')) # Add per-object css classes support css_handler = getattr( self, 'get_{}_css'.format(action_name), None) if callable(css_handler): css_classes = css_handler(obj=obj) else: try: css_classes = action_func.css_classes except AttributeError: css_classes = '' # If the form is submitted, we have no information about the # requested action. # Hence we need all data to be encoded using the action name. action_data = [ # required to distinguish between multiple inlines for the same model self.__class__.__name__.lower(), self._get_admin_type(), action_name, obj._meta.app_label, obj._meta.model_name, str(obj.pk), ] buttons.append( ''.format( '_action__{}'.format('__'.join(action_data)), description, css_classes, ) ) return mark_safe('
tags as a workaround for invalid html return mark_safe('
{}'.format(html))
render_inline_actions.short_description = _("Actions")
render_inline_actions.allow_tags = True
def get_fields(self, request, obj=None):
# store `request` for `get_inline_actions`
self._request = request
fields = super().get_fields(request, obj)
if self.inline_actions is not None: # is it explicitly disabled?
fields = list(fields)
if 'render_inline_actions' not in fields:
fields.append('render_inline_actions')
return fields
class InlineActionsModelAdminMixin(BaseInlineActionsMixin):
class Media:
css = {
"all": (
"inline_actions/css/inline_actions.css",
)
}
def get_list_display(self, request):
# store `request` for `get_inline_actions`
self._request = request
fields = super().get_list_display(request)
if self.inline_actions is not None: # is it explicitly disabled?
fields = list(fields)
if 'render_inline_actions' not in fields:
fields.append('render_inline_actions')
return fields
def get_fields(self, request, obj=None):
# store `request` for `get_inline_actions`
self._request = request
fields = super().get_fields(request, obj=obj)
if not self.fields:
# django adds all readonly fields by default
# if `self.fields` is not defined we don't want to include
# `render_inline_actions
fields.remove('render_inline_actions')
return fields
def _execute_action(self, request, model_admin, action, obj, parent_obj=None):
"""
Tries to execute the requested action and returns a `HttpResponse`.
raises
ActionNotCallable - When action is not a function
"""
# execute action
func = getattr(model_admin, action, None)
try:
response = func(request, obj, parent_obj=parent_obj)
except TypeError as e:
raise ActionNotCallable(model_admin, action) from e
# we should receive an HttpResponse
if isinstance(response, HttpResponse):
return response
# otherwise redirect back
if parent_obj is None: # InlineActionsMixin.MODEL_ADMIN:
# redirect to `changelist`
url = reverse(
'admin:{}_{}_changelist'.format(
obj._meta.app_label,
obj._meta.model_name,
),
)
else:
# redirect to `changeform`
url = reverse(
'admin:{}_{}_change'.format(
parent_obj._meta.app_label,
parent_obj._meta.model_name,
),
args=(parent_obj.pk,)
)
# readd query string
query = request.META['QUERY_STRING'] or request.GET.urlencode()
if query:
url = '{}?{}'.format(url, query)
return redirect(url)
def _handle_action(self, request, object_id=None):
"""
Resolve and executes the action issued by the current request.
If no action was triggered, it does nothing.
Returns `HttpResponse` or `None`
"""
all_actions = [key for key in list(request.POST.keys())
if key.startswith('_action__')]
if request.method == 'POST' and all_actions:
assert len(all_actions) == 1
raw_action_name = all_actions[0].replace('_action__', '', 1)
# resolve action and target models
raw_action_parts = raw_action_name.split('__')
admin_class_name, admin_type = raw_action_parts[:2]
action, app_label, model_name, object_pk = raw_action_parts[2:]
model = apps.get_model(app_label=app_label,
model_name=model_name)
parent_obj = self.get_object(request, object_id)
# find action and execute
if admin_type == self.MODEL_ADMIN:
model_admin = self
obj = model_admin.get_queryset(request).get(pk=object_pk)
# parent_obj is None because `object_id` is None
else:
for inline in self.get_inline_instances(request):
inline_class_name = inline.__class__.__name__.lower()
matches_inline_class = inline_class_name == admin_class_name
matches_model = inline.model == model
if not matches_model or not matches_inline_class:
continue
model_admin = inline
obj = model_admin.get_queryset(request).get(pk=object_pk)
if model_admin:
return self._execute_action(
request, model_admin, action, obj, parent_obj)
return None
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
# handle requested action if required
response = self._handle_action(request, object_id=object_id)
if response:
return response
# continue normally
return super().changeform_view(
request, object_id, form_url, extra_context)
def changelist_view(self, request, extra_context=None):
# handle requested action if required
response = self._handle_action(request)
if response:
return response
# continue normally
return super().changelist_view(
request, extra_context)
PK ! 0= ; inline_actions/static/inline_actions/css/inline_actions.css.field-render_inline_actions > p,
.field-render_inline_actions label + p {
display: none;
}
#changelist table .submit_row.inline_actions input,
.submit_row.inline_actions input {
padding: 0px 5px;
margin: 0 10px 0 0;
cursor: pointer;
}
PK ! nN - django_inline_actions-2.2.0.dist-info/LICENSECopyright (c) 2016, Alexander Frenzel