mirror of
https://github.com/tencentmusic/cube-studio.git
synced 2024-12-21 06:19:31 +08:00
325 lines
11 KiB
Python
325 lines
11 KiB
Python
"""Contains the logic to create cohesive forms on the explore view"""
|
||
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
|
||
from wtforms import Field
|
||
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget, BS3PasswordFieldWidget, DatePickerWidget, DateTimePickerWidget, Select2ManyWidget, Select2Widget
|
||
from wtforms import widgets
|
||
from myapp import app
|
||
|
||
conf = app.config
|
||
|
||
from wtforms.validators import DataRequired, Length, NumberRange, Optional, Regexp, ValidationError
|
||
|
||
# 处理完再校验
|
||
class JsonValidator(object):
|
||
def __init__(self):
|
||
pass
|
||
|
||
def __call__(self, form, field):
|
||
data = field.data
|
||
if data is None:
|
||
raise ValidationError('input must json')
|
||
try:
|
||
json.loads(data)
|
||
except Exception as e:
|
||
raise ValidationError("JSON is not valid :%s" % str(e))
|
||
|
||
|
||
class MyCommaSeparatedListField(Field):
|
||
widget = BS3TextFieldWidget()
|
||
|
||
def _value(self):
|
||
if self.data:
|
||
return u", ".join(self.data)
|
||
else:
|
||
return u""
|
||
|
||
def process_formdata(self, valuelist):
|
||
if valuelist:
|
||
self.data = [x.strip() for x in valuelist[0].split(",")]
|
||
else:
|
||
self.data = []
|
||
|
||
|
||
def filter_not_empty_values(value):
|
||
"""Returns a list of non empty values or None"""
|
||
if not value:
|
||
return None
|
||
data = [x for x in value if x]
|
||
if not data:
|
||
return None
|
||
return data
|
||
|
||
|
||
import pysnooper, datetime, time, json
|
||
from wtforms.widgets.core import Markup, html_params
|
||
|
||
try:
|
||
from html import escape
|
||
except ImportError:
|
||
from cgi import escape
|
||
from wtforms.compat import text_type, iteritems
|
||
|
||
|
||
class MyCodeArea(object):
|
||
def __init__(self, code=''):
|
||
self.code = code
|
||
|
||
def __call__(self, field, **kwargs):
|
||
if self.code:
|
||
return Markup('<pre><code>%s</code></pre>' % (self.code,))
|
||
else:
|
||
return Markup('<pre><code>%s</code></pre>' % (field._value(),))
|
||
# return Markup('<pre><code>%s</code></pre>' % (field._value(),))
|
||
|
||
|
||
from wtforms import widgets
|
||
|
||
|
||
class MyBS3TextAreaFieldWidget(widgets.TextArea):
|
||
def __init__(self, rows=3, readonly=0, expand_filed=None, tips=None): # 扩展成list类型字段
|
||
self.rows = rows
|
||
self.readonly = readonly
|
||
self.expand_filed = expand_filed
|
||
self.tips = tips
|
||
return super(MyBS3TextAreaFieldWidget, self).__init__()
|
||
|
||
def __call__(self, field, **kwargs):
|
||
kwargs["class"] = u"form-control"
|
||
kwargs["rows"] = self.rows
|
||
if field.label:
|
||
kwargs["placeholder"] = field.label.text
|
||
if self.readonly:
|
||
kwargs['readonly'] = 'readonly'
|
||
return super(MyBS3TextAreaFieldWidget, self).__call__(field, **kwargs)
|
||
|
||
|
||
class MyBS3TextFieldWidget(widgets.TextInput):
|
||
def __init__(self, value='', readonly=0, is_date=False, is_date_range=False):
|
||
self.value = value
|
||
self.readonly = readonly
|
||
self.is_date = is_date
|
||
self.is_date_range = is_date_range
|
||
return super(MyBS3TextFieldWidget, self).__init__()
|
||
|
||
def __call__(self, field, **kwargs):
|
||
kwargs["class"] = u"form-control"
|
||
if field.label:
|
||
kwargs["placeholder"] = field.label.text
|
||
if "name_" in kwargs:
|
||
field.name = kwargs["name_"]
|
||
if self.value:
|
||
kwargs['value'] = self.value
|
||
if self.readonly:
|
||
kwargs['readonly'] = 'readonly'
|
||
return super(MyBS3TextFieldWidget, self).__call__(field, **kwargs)
|
||
|
||
|
||
class MyLineSeparatedListField(Field):
|
||
widget = MyBS3TextAreaFieldWidget()
|
||
|
||
# 前端要显示的值
|
||
def _value(self):
|
||
if self.data:
|
||
return u"\n".join(self.data) # 数据库里面的数据是list
|
||
else:
|
||
return u""
|
||
|
||
# 发送到后端的值
|
||
def process_formdata(self, valuelist):
|
||
if valuelist:
|
||
self.data = [x.strip() for x in valuelist[0].split("\n")]
|
||
else:
|
||
self.data = []
|
||
|
||
|
||
class MyJSONField(Field):
|
||
widget = MyBS3TextAreaFieldWidget(rows=3)
|
||
|
||
# 前端要显示的值
|
||
def _value(self):
|
||
if self.data:
|
||
# return self.data #
|
||
if type(self.data) == str: # 如果是字符集就原样返回
|
||
return self.data
|
||
return json.dumps(self.data, indent=4, ensure_ascii=False) # 数据库里面的数据是list
|
||
else:
|
||
return u"{}"
|
||
|
||
# # 后端发送前端时的数据处理,处理完以后使用_value()进行显示
|
||
# @pysnooper.snoop()
|
||
# def process_data(self, value):
|
||
# try:
|
||
# if value:
|
||
# self.data = json.loads(value)
|
||
# else:
|
||
# self.data = {}
|
||
# except Exception as e:
|
||
# self.data={}
|
||
# print(self.data,type(self.data))
|
||
|
||
# 发送到后端的值
|
||
def process_formdata(self, valuelist):
|
||
try:
|
||
if valuelist:
|
||
self.data = json.loads(valuelist[0])
|
||
else:
|
||
self.data = {}
|
||
except Exception as e:
|
||
self.data = valuelist[0] # self.default # 如果出错,self.data就是原始字符串了。
|
||
raise ValidationError('input must json:' + str(e))
|
||
|
||
|
||
from wtforms.widgets.core import escape_html
|
||
from flask_babel import lazy_gettext as _
|
||
|
||
|
||
class MySelect2Widget(object):
|
||
extra_classes = None
|
||
|
||
def __init__(self, extra_classes=None, style=None, multiple=False, new_web=True, value='', can_input=False, conten2choices=False, retry_info=False):
|
||
self.extra_classes = extra_classes
|
||
self.style = style or u"width:350px"
|
||
self.multiple = multiple
|
||
self.value = value
|
||
self.new_web = new_web
|
||
self.can_input = can_input
|
||
self.conten2choices = conten2choices
|
||
self.retry_info = retry_info
|
||
|
||
# @pysnooper.snoop()
|
||
def __call__(self, field, **kwargs):
|
||
kwargs["class"] = u"my_select2 form-control"
|
||
if self.extra_classes:
|
||
kwargs["class"] = kwargs["class"] + " " + self.extra_classes
|
||
kwargs["style"] = self.style
|
||
kwargs["data-placeholder"] = _("Select Value")
|
||
if "name_" in kwargs:
|
||
field.name = kwargs["name_"]
|
||
|
||
kwargs.setdefault('id', field.id)
|
||
if self.multiple:
|
||
kwargs['multiple'] = True
|
||
if 'required' not in kwargs and 'required' in getattr(field, 'flags', []):
|
||
kwargs['required'] = True
|
||
if self.new_web:
|
||
fun = "set_change('%s')" % field.name
|
||
else:
|
||
fun = ''
|
||
|
||
html = ['''<select %s id=%s onchange="%s">''' %
|
||
(html_params(name=field.name, **kwargs), field.name, fun)]
|
||
for val, label, selected in field.iter_choices():
|
||
if self.value:
|
||
if str(val) == str(self.value):
|
||
html.append(self.render_option(val, label, selected=True))
|
||
else:
|
||
html.append(self.render_option(val, label, selected=False))
|
||
else:
|
||
html.append(self.render_option(val, label, selected))
|
||
html.append('</select>')
|
||
return Markup(''.join(html))
|
||
|
||
@classmethod
|
||
def render_option(cls, value, label, selected, **kwargs):
|
||
if value is True:
|
||
# Handle the special case of a 'True' value.
|
||
value = text_type(value)
|
||
|
||
options = dict(kwargs, value=value)
|
||
if selected:
|
||
options['selected'] = True
|
||
return Markup('<option %s>%s</option>' % (html_params(**options), escape_html(label, quote=False)))
|
||
|
||
|
||
# json编辑框
|
||
class MyJsonIde(object):
|
||
def __call__(self, field, **kwargs):
|
||
return Markup('<pre><code>%s</code></pre>' % (field._value(),))
|
||
# return Markup('<pre><code>%s</code></pre>' % (field._value(),))
|
||
|
||
|
||
class MySelect2ManyWidget(widgets.Select):
|
||
extra_classes = None
|
||
|
||
def __init__(self, extra_classes=None, style=None, can_input=False):
|
||
self.extra_classes = extra_classes
|
||
self.style = style or u"width:250px"
|
||
self.can_input = can_input
|
||
return super(MySelect2ManyWidget, self).__init__()
|
||
|
||
|
||
from wtforms.fields.core import SelectField
|
||
|
||
|
||
class MySelectMultipleField(SelectField):
|
||
"""
|
||
No different from a normal select field, except this one can take (and
|
||
validate) multiple choices. You'll need to specify the HTML `size`
|
||
attribute to the select field when rendering.
|
||
"""
|
||
widget = widgets.Select(multiple=True)
|
||
|
||
def iter_choices(self):
|
||
for value, label in self.choices:
|
||
selected = self.data is not None and self.coerce(value) in self.data
|
||
yield (value, label, selected)
|
||
|
||
# 将数据库数据处理成前端需要的数据.post的时候也会调用一遍,那时value为None
|
||
# @pysnooper.snoop(watch_explode='value')
|
||
def process_data(self, value):
|
||
try:
|
||
if value:
|
||
self.data = list(self.coerce(v) for v in value.split(','))
|
||
self.data = [x for x in self.data if x]
|
||
# print(self.data)
|
||
else:
|
||
self.data = None
|
||
except (ValueError, TypeError):
|
||
self.data = None
|
||
|
||
# @pysnooper.snoop(watch_explode='valuelist')
|
||
def process_formdata(self, valuelist):
|
||
try:
|
||
self.data = ','.join(list(self.coerce(x) for x in valuelist))
|
||
# print(self.data)
|
||
except ValueError:
|
||
raise ValueError(self.gettext('Invalid choice(s): one or more data inputs could not be coerced'))
|
||
|
||
def pre_validate(self, form):
|
||
pass
|
||
|
||
|
||
from flask_appbuilder.widgets import FormWidget
|
||
from flask_appbuilder._compat import as_unicode
|
||
|
||
|
||
class MySearchWidget(FormWidget):
|
||
template = "appbuilder/general/widgets/search.html"
|
||
filters = None
|
||
|
||
def __init__(self, **kwargs):
|
||
self.filters = kwargs.get("filters")
|
||
self.help_url = kwargs.get("help_url", '')
|
||
return super(MySearchWidget, self).__init__(**kwargs)
|
||
|
||
def __call__(self, **kwargs):
|
||
""" create dict labels based on form """
|
||
""" create dict of form widgets """
|
||
""" create dict of possible filters """
|
||
""" create list of active filters """
|
||
label_columns = {}
|
||
form_fields = {}
|
||
search_filters = {}
|
||
dict_filters = self.filters.get_search_filters()
|
||
for col in self.template_args["include_cols"]:
|
||
label_columns[col] = as_unicode(self.template_args["form"][col].label.text)
|
||
form_fields[col] = self.template_args["form"][col]()
|
||
search_filters[col] = [as_unicode(flt.name) for flt in dict_filters[col]]
|
||
|
||
kwargs["help_url"] = self.help_url
|
||
kwargs["label_columns"] = label_columns
|
||
kwargs["form_fields"] = form_fields
|
||
kwargs["search_filters"] = search_filters
|
||
kwargs["active_filters"] = self.filters.get_filters_values_tojson()
|
||
return super(MySearchWidget, self).__call__(**kwargs)
|