123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- from flask import request, redirect
- from flask_admin import tools
- from flask_admin._compat import text_type
- from flask_admin.helpers import get_redirect_target, flash_errors
- def action(name, text, confirmation=None):
- """
- Use this decorator to expose actions that span more than one
- entity (model, file, etc)
- :param name:
- Action name
- :param text:
- Action text.
- :param confirmation:
- Confirmation text. If not provided, action will be executed
- unconditionally.
- """
- def wrap(f):
- f._action = (name, text, confirmation)
- return f
- return wrap
- class ActionsMixin(object):
- """
- Actions mixin.
- In some cases, you might work with more than one "entity" (model, file, etc) in
- your admin view and will want to perform actions on a group of entities simultaneously.
- In this case, you can add this functionality by doing this:
- 1. Add this mixin to your administrative view class
- 2. Call `init_actions` in your class constructor
- 3. Expose actions view
- 4. Import `actions.html` library and add call library macros in your template
- """
- def __init__(self):
- """
- Default constructor.
- """
- self._actions = []
- self._actions_data = {}
- def init_actions(self):
- """
- Initialize list of actions for the current administrative view.
- """
- self._actions = []
- self._actions_data = {}
- for p in dir(self):
- attr = tools.get_dict_attr(self, p)
- if hasattr(attr, '_action'):
- name, text, desc = attr._action
- self._actions.append((name, text))
- # TODO: Use namedtuple
- # Reason why we need getattr here - what's in attr is not
- # bound to the object.
- self._actions_data[name] = (getattr(self, p), text, desc)
- def is_action_allowed(self, name):
- """
- Verify if action with `name` is allowed.
- :param name:
- Action name
- """
- return True
- def get_actions_list(self):
- """
- Return a list and a dictionary of allowed actions.
- """
- actions = []
- actions_confirmation = {}
- for act in self._actions:
- name, text = act
- if self.is_action_allowed(name):
- actions.append((name, text_type(text)))
- confirmation = self._actions_data[name][2]
- if confirmation:
- actions_confirmation[name] = text_type(confirmation)
- return actions, actions_confirmation
- def handle_action(self, return_view=None):
- """
- Handle action request.
- :param return_view:
- Name of the view to return to after the request.
- If not provided, will return user to the return url in the form
- or the list view.
- """
- form = self.action_form()
- if self.validate_form(form):
- # using getlist instead of FieldList for backward compatibility
- ids = request.form.getlist('rowid')
- action = form.action.data
- handler = self._actions_data.get(action)
- if handler and self.is_action_allowed(action):
- response = handler[0](ids)
- if response is not None:
- return response
- else:
- flash_errors(form, message='Failed to perform action. %(error)s')
- if return_view:
- url = self.get_url('.' + return_view)
- else:
- url = get_redirect_target() or self.get_url('.index_view')
- return redirect(url)
|