Admin Actions in daily usage often require one or more arguments. This extension provides an easy way to display a form to fill in what needs to be passed to the actions. Namely:
Create a form that holds all the fields needed for any action and set action_form on your JumboModelAdmin pointing to that form.
Caution
Set any additional field as required = False otherwise all actions that don’t define that will not let the form validate and you’ll get a ConfigurationError
Fields defined in this action may be used in different actions. A field required in one action may not be needed in another. See below how to obtain this
Configure which fields are needed for any action in action_form.fields_map dict. See example below
Modify change_list.html template to add
- templatetag to render admin/actions.html (inluded in {jmb.jadmin}result_list)
- javascript to toggle visibility of the fields
this step is already done in jmb.jadmin provided template
When ModelAdmin has actions enabled, Django creates a form and places it as attribute action_form, thought is not officially documented. This action will hold
Entending and modifying that form we make available any fields defined in it. The selected row will be available as a queryset, as usual.
You can use JumboModelAdmin.get_action_form_instance() to get an already validated form instance
This is used to specify a different form to add extra action fields. To use this you need override class JumboActionForm. It’s a good idea define these forms in admin_forms.py or in admin/forms.py:
from jmb.jadmin import JumboActionForm
class NewsletterActionForm(JumboActionForm):
customization = forms.CharField(widget=forms.Textarea, required=False)
mailing_list = forms.ModelChoiceField(
queryset=MailingList.objects.filter(status=1),
label=_('Mailing list'),
required=False, # IMPORTANT
# This is automatically added if not specified. Used from JS to toggle extra action fields
widget=forms.Select(attrs={'id': 'mailing_list', 'class': 'extra_action_field'})
)
fields_map = {
'export_action': ['output_type'],
'clone': [], ## not needed for actions that do not require a field
'send_newsletter': ['mailing_list', 'customization'],
'resend_newsletter': ['mailing_list:required'],
}
While your ModelAdmin can be sort of:
from jmb.jadmin import JumboModelAdmin
from .admin_form import NewsletterActionForm
class NewsletterAdmin(JumboModelAdmin):
def send_newsletter(self, request, queryset):
form = self.get_action_form_instance(request)
if form.cleaned_data['field_name']:
...
action_form = NewsletterActionForm
A dictionary to specify action and its extra fields to complete operation. As in the example above you can have:
fields_map = {
'clone': [],
'export_action': ['output_type'],
'resend_newsletter': ['mailing_list:required', 'start_time'],
}
New in version 0.9: This field was previously named action_form_fields and was set on ModelAdmin
If you use export action to export data as it is currently the deafult in jmb.jadmin, we use a fields_map as follows:
fields_map = {
'export_action': ['output_type'],
}
that you must retain if you want to use that action.
It’s a handy function that creates the form in the same way django creates it, and returns a validated form.
It’s possible to have fields to show in a modal. This is particularly usefull when the fields to be compiled are a lot.
You need to setup the template change_list.html to host the form and the needed javascript. follows a possible implementation that is working correctly. Be sure to understand it and change according to your needs:
{% extends "jadmin:admin/change_list.html" %}
{% load result_list admin_static admin_list i18n admin_urls %}
{% block extrahead %}
{{ block.super }}
<script>
$(document).ready(function ($) {
$('select[name=action]').change(function(e){
var value = $('select[name=action]').val();
if (value == 'send_newsletter') {
$("#actionModal").modal('show');
$(".actions").appendTo(".modal-body");
$('.double').hide();
$('.field_action').hide();
$('#customization').css('width', '500px'); // a text field named customization
$('#actionModal').on('hide.bs.modal', function (e) {
$(".actions").insertAfter($('input[name=csrfmiddlewaretoken]'));
$('.double').show();
$('.field_action').show();
$('select[name=action]').val('').prop('selected', true).change();
});
}
});
});
</script>
{% endblock %}
{% block result_list %}
{{ block.super }}
<div class="modal hide" id="actionModal">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h3>My super modal action</h3>
</div>
<div class="modal-body"></div>
</div>
{% endblock %}
The default ActionForm with some logic to implement required fields according to selected action.
Check that no field is required other than action. That would make the validation fail. If you need a required field for an action add :required in the declaration in fields_map as documented above
mapping between action name and fields needed for the action
Return a list of field_names for action action Parses fields_map attribute
Parameters: | action – action for which field_names are required. If action is None it looks for selected action in self.cleaned_data. If no action is selected it returns an empty list |
---|
Return a list of required field_names for action action Parses fields_map attribute
Parameters: | action – action for which field_names are required. If action is None it looks for selected action in self.cleaned_data. If no action is selected it returns an empty list |
---|