| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- # coding:utf-8
- from itertools import chain
- import xadmin
- from django import forms
- from django.db.models import ManyToManyField
- from django.forms.utils import flatatt
- from django.template import loader
- from django.utils.encoding import force_text
- from django.utils.html import escape, conditional_escape
- from django.utils.safestring import mark_safe
- from xadmin.util import vendor
- from xadmin.views import BaseAdminPlugin, ModelFormAdminView
- class SelectMultipleTransfer(forms.SelectMultiple):
- @property
- def media(self):
- return vendor('xadmin.widget.select-transfer.js', 'xadmin.widget.select-transfer.css')
- def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
- self.verbose_name = verbose_name
- self.is_stacked = is_stacked
- super(SelectMultipleTransfer, self).__init__(attrs, choices)
- def render_opt(self, selected_choices, option_value, option_label):
- option_value = force_text(option_value)
- return u'<option value="%s">%s</option>' % (
- escape(option_value), conditional_escape(force_text(option_label))), bool(option_value in selected_choices)
- def render(self, name, value, attrs=None, choices=()):
- if attrs is None:
- attrs = {}
- attrs['class'] = ''
- if self.is_stacked:
- attrs['class'] += 'stacked'
- if value is None:
- value = []
- final_attrs = self.build_attrs(attrs, extra_attrs={'name': name})
- selected_choices = set(force_text(v) for v in value)
- available_output = []
- chosen_output = []
- for option_value, option_label in chain(self.choices, choices):
- if isinstance(option_label, (list, tuple)):
- available_output.append(u'<optgroup label="%s">' %
- escape(force_text(option_value)))
- for option in option_label:
- output, selected = self.render_opt(
- selected_choices, *option)
- if selected:
- chosen_output.append(output)
- else:
- available_output.append(output)
- available_output.append(u'</optgroup>')
- else:
- output, selected = self.render_opt(
- selected_choices, option_value, option_label)
- if selected:
- chosen_output.append(output)
- else:
- available_output.append(output)
- context = {
- 'verbose_name': self.verbose_name,
- 'attrs': attrs,
- 'field_id': attrs['id'],
- 'flatatts': flatatt(final_attrs),
- 'available_options': u'\n'.join(available_output),
- 'chosen_options': u'\n'.join(chosen_output),
- }
- return mark_safe(loader.render_to_string('xadmin/forms/transfer.html', context))
- class SelectMultipleDropdown(forms.SelectMultiple):
- @property
- def media(self):
- return vendor('multiselect.js', 'multiselect.css', 'xadmin.widget.multiselect.js')
- def render(self, name, value, attrs=None, choices=()):
- if attrs is None:
- attrs = {}
- attrs['class'] = 'selectmultiple selectdropdown'
- return super(SelectMultipleDropdown, self).render(name, value, attrs, choices)
- class M2MSelectPlugin(BaseAdminPlugin):
- def init_request(self, *args, **kwargs):
- return hasattr(self.admin_view, 'style_fields') and \
- (
- 'm2m_transfer' in self.admin_view.style_fields.values() or
- 'm2m_dropdown' in self.admin_view.style_fields.values()
- )
- def get_field_style(self, attrs, db_field, style, **kwargs):
- if style == 'm2m_transfer' and isinstance(db_field, ManyToManyField):
- return {'widget': SelectMultipleTransfer(db_field.verbose_name, False), 'help_text': ''}
- if style == 'm2m_dropdown' and isinstance(db_field, ManyToManyField):
- return {'widget': SelectMultipleDropdown, 'help_text': ''}
- return attrs
- xadmin.site.register_plugin(M2MSelectPlugin, ModelFormAdminView)
|