123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- from flask import json
- from jinja2 import escape
- from wtforms.widgets import HTMLString, html_params
- from flask_admin._compat import as_unicode, text_type
- from flask_admin.babel import gettext
- from flask_admin.helpers import get_url
- from flask_admin.form import RenderTemplateWidget
- class InlineFieldListWidget(RenderTemplateWidget):
- def __init__(self):
- super(InlineFieldListWidget, self).__init__('admin/model/inline_field_list.html')
- class InlineFormWidget(RenderTemplateWidget):
- def __init__(self):
- super(InlineFormWidget, self).__init__('admin/model/inline_form.html')
- def __call__(self, field, **kwargs):
- kwargs.setdefault('form_opts', getattr(field, 'form_opts', None))
- return super(InlineFormWidget, self).__call__(field, **kwargs)
- class AjaxSelect2Widget(object):
- def __init__(self, multiple=False):
- self.multiple = multiple
- def __call__(self, field, **kwargs):
- kwargs.setdefault('data-role', 'select2-ajax')
- kwargs.setdefault('data-url', get_url('.ajax_lookup', name=field.loader.name))
- allow_blank = getattr(field, 'allow_blank', False)
- if allow_blank and not self.multiple:
- kwargs['data-allow-blank'] = u'1'
- kwargs.setdefault('id', field.id)
- kwargs.setdefault('type', 'hidden')
- if self.multiple:
- result = []
- ids = []
- for value in field.data:
- data = field.loader.format(value)
- result.append(data)
- ids.append(as_unicode(data[0]))
- separator = getattr(field, 'separator', ',')
- kwargs['value'] = separator.join(ids)
- kwargs['data-json'] = json.dumps(result)
- kwargs['data-multiple'] = u'1'
- else:
- data = field.loader.format(field.data)
- if data:
- kwargs['value'] = data[0]
- kwargs['data-json'] = json.dumps(data)
- placeholder = field.loader.options.get('placeholder', gettext('Please select model'))
- kwargs.setdefault('data-placeholder', placeholder)
- return HTMLString('<input %s>' % html_params(name=field.name, **kwargs))
- class XEditableWidget(object):
- """
- WTForms widget that provides in-line editing for the list view.
- Determines how to display the x-editable/ajax form based on the
- field inside of the FieldList (StringField, IntegerField, etc).
- """
- def __call__(self, field, **kwargs):
- kwargs.setdefault('data-value', kwargs.pop('display_value', ''))
- kwargs.setdefault('data-role', 'x-editable')
- kwargs.setdefault('data-url', './ajax/update/')
- kwargs.setdefault('id', field.id)
- kwargs.setdefault('name', field.name)
- kwargs.setdefault('href', '#')
- if not kwargs.get('pk'):
- raise Exception('pk required')
- kwargs['data-pk'] = str(kwargs.pop("pk"))
- kwargs['data-csrf'] = kwargs.pop("csrf", "")
- kwargs = self.get_kwargs(field, kwargs)
- return HTMLString(
- '<a %s>%s</a>' % (html_params(**kwargs),
- escape(kwargs['data-value']))
- )
- def get_kwargs(self, field, kwargs):
- """
- Return extra kwargs based on the field type.
- """
- if field.type == 'StringField':
- kwargs['data-type'] = 'text'
- elif field.type == 'TextAreaField':
- kwargs['data-type'] = 'textarea'
- kwargs['data-rows'] = '5'
- elif field.type == 'BooleanField':
- kwargs['data-type'] = 'select'
- # data-source = dropdown options
- kwargs['data-source'] = json.dumps([
- {'value': '', 'text': gettext('No')},
- {'value': '1', 'text': gettext('Yes')}
- ])
- kwargs['data-role'] = 'x-editable-boolean'
- elif field.type in ['Select2Field', 'SelectField']:
- kwargs['data-type'] = 'select'
- choices = [{'value': x, 'text': y} for x, y in field.choices]
- # prepend a blank field to choices if allow_blank = True
- if getattr(field, 'allow_blank', False):
- choices.insert(0, {'value': '__None', 'text': ''})
- # json.dumps fixes issue with unicode strings not loading correctly
- kwargs['data-source'] = json.dumps(choices)
- elif field.type == 'DateField':
- kwargs['data-type'] = 'combodate'
- kwargs['data-format'] = 'YYYY-MM-DD'
- kwargs['data-template'] = 'YYYY-MM-DD'
- elif field.type == 'DateTimeField':
- kwargs['data-type'] = 'combodate'
- kwargs['data-format'] = 'YYYY-MM-DD HH:mm:ss'
- kwargs['data-template'] = 'YYYY-MM-DD HH:mm:ss'
- # x-editable-combodate uses 1 minute increments
- kwargs['data-role'] = 'x-editable-combodate'
- elif field.type == 'TimeField':
- kwargs['data-type'] = 'combodate'
- kwargs['data-format'] = 'HH:mm:ss'
- kwargs['data-template'] = 'HH:mm:ss'
- kwargs['data-role'] = 'x-editable-combodate'
- elif field.type == 'IntegerField':
- kwargs['data-type'] = 'number'
- elif field.type in ['FloatField', 'DecimalField']:
- kwargs['data-type'] = 'number'
- kwargs['data-step'] = 'any'
- elif field.type in ['QuerySelectField', 'ModelSelectField',
- 'QuerySelectMultipleField', 'KeyPropertyField']:
- # QuerySelectField and ModelSelectField are for relations
- kwargs['data-type'] = 'select'
- choices = []
- selected_ids = []
- for value, label, selected in field.iter_choices():
- try:
- label = text_type(label)
- except TypeError:
- # unable to display text value
- label = ''
- choices.append({'value': text_type(value), 'text': label})
- if selected:
- selected_ids.append(value)
- # blank field is already included if allow_blank
- kwargs['data-source'] = json.dumps(choices)
- if field.type == 'QuerySelectMultipleField':
- kwargs['data-type'] = 'select2'
- kwargs['data-role'] = 'x-editable-select2-multiple'
- # must use id instead of text or prefilled values won't work
- separator = getattr(field, 'separator', ',')
- kwargs['data-value'] = separator.join(selected_ids)
- else:
- raise Exception('Unsupported field type: %s' % (type(field),))
- return kwargs
|