cube-studio/myapp/forms.py

325 lines
11 KiB
Python
Raw Normal View History

2021-08-17 17:00:34 +08:00
"""Contains the logic to create cohesive forms on the explore view"""
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
2023-04-06 23:03:18 +08:00
from wtforms import Field
2023-09-03 21:17:55 +08:00
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget, BS3PasswordFieldWidget, DatePickerWidget, DateTimePickerWidget, Select2ManyWidget, Select2Widget
2023-04-06 23:03:18 +08:00
from wtforms import widgets
2021-08-17 17:00:34 +08:00
from myapp import app
conf = app.config
2023-09-03 21:17:55 +08:00
from wtforms.validators import DataRequired, Length, NumberRange, Optional, Regexp, ValidationError
2021-08-17 17:00:34 +08:00
# 处理完再校验
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:
2023-09-03 21:17:55 +08:00
raise ValidationError("JSON is not valid :%s" % str(e))
2021-08-17 17:00:34 +08:00
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
2023-09-03 21:17:55 +08:00
import pysnooper, datetime, time, json
2023-12-11 13:25:07 +08:00
from wtforms.widgets.core import Markup, html_params
2023-04-06 23:03:18 +08:00
try:
from html import escape
except ImportError:
from cgi import escape
from wtforms.compat import text_type, iteritems
2021-08-17 17:00:34 +08:00
class MyCodeArea(object):
def __init__(self, code=''):
2023-09-03 21:17:55 +08:00
self.code = code
2021-08-17 17:00:34 +08:00
def __call__(self, field, **kwargs):
if self.code:
2023-12-11 13:25:07 +08:00
return Markup('<pre><code>%s</code></pre>' % (self.code,))
2021-08-17 17:00:34 +08:00
else:
2023-12-11 13:25:07 +08:00
return Markup('<pre><code>%s</code></pre>' % (field._value(),))
# return Markup('<pre><code>%s</code></pre>' % (field._value(),))
2021-08-17 17:00:34 +08:00
2023-09-03 21:17:55 +08:00
2021-08-17 17:00:34 +08:00
from wtforms import widgets
2023-09-03 21:17:55 +08:00
2021-08-17 17:00:34 +08:00
class MyBS3TextAreaFieldWidget(widgets.TextArea):
2023-09-03 21:17:55 +08:00
def __init__(self, rows=3, readonly=0, expand_filed=None, tips=None): # 扩展成list类型字段
self.rows = rows
2021-08-17 17:00:34 +08:00
self.readonly = readonly
2023-09-03 21:17:55 +08:00
self.expand_filed = expand_filed
2023-04-06 23:03:18 +08:00
self.tips = tips
2021-08-17 17:00:34 +08:00
return super(MyBS3TextAreaFieldWidget, self).__init__()
2022-08-28 20:24:10 +08:00
2021-08-17 17:00:34 +08:00
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:
2023-09-03 21:17:55 +08:00
kwargs['readonly'] = 'readonly'
2021-08-17 17:00:34 +08:00
return super(MyBS3TextAreaFieldWidget, self).__call__(field, **kwargs)
class MyBS3TextFieldWidget(widgets.TextInput):
2023-09-03 21:17:55 +08:00
def __init__(self, value='', readonly=0, is_date=False, is_date_range=False):
self.value = value
2021-08-17 17:00:34 +08:00
self.readonly = readonly
2023-09-03 21:17:55 +08:00
self.is_date = is_date
self.is_date_range = is_date_range
2021-08-17 17:00:34 +08:00
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:
2023-09-03 21:17:55 +08:00
kwargs['readonly'] = 'readonly'
2021-08-17 17:00:34 +08:00
return super(MyBS3TextFieldWidget, self).__call__(field, **kwargs)
class MyLineSeparatedListField(Field):
widget = MyBS3TextAreaFieldWidget()
# 前端要显示的值
def _value(self):
if self.data:
2023-09-03 21:17:55 +08:00
return u"\n".join(self.data) # 数据库里面的数据是list
2021-08-17 17:00:34 +08:00
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 #
2023-09-03 21:17:55 +08:00
if type(self.data) == str: # 如果是字符集就原样返回
2021-08-17 17:00:34 +08:00
return self.data
2023-09-03 21:17:55 +08:00
return json.dumps(self.data, indent=4, ensure_ascii=False) # 数据库里面的数据是list
2021-08-17 17:00:34 +08:00
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:
2023-09-03 21:17:55 +08:00
self.data = valuelist[0] # self.default # 如果出错self.data就是原始字符串了。
raise ValidationError('input must json:' + str(e))
2021-08-17 17:00:34 +08:00
from wtforms.widgets.core import escape_html
from flask_babel import lazy_gettext as _
2023-09-03 21:17:55 +08:00
class MySelect2Widget(object):
2021-08-17 17:00:34 +08:00
extra_classes = None
2023-09-03 21:17:55 +08:00
def __init__(self, extra_classes=None, style=None, multiple=False, new_web=True, value='', can_input=False, conten2choices=False, retry_info=False):
2021-08-17 17:00:34 +08:00
self.extra_classes = extra_classes
self.style = style or u"width:350px"
self.multiple = multiple
2023-09-03 21:17:55 +08:00
self.value = value
self.new_web = new_web
self.can_input = can_input
2023-09-03 21:17:55 +08:00
self.conten2choices = conten2choices
self.retry_info = retry_info
2021-08-17 17:00:34 +08:00
# @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:
2023-09-03 21:17:55 +08:00
fun = "set_change('%s')" % field.name
2021-08-17 17:00:34 +08:00
else:
2023-09-03 21:17:55 +08:00
fun = ''
2021-08-17 17:00:34 +08:00
html = ['''<select %s id=%s onchange="%s">''' %
2023-09-03 21:17:55 +08:00
(html_params(name=field.name, **kwargs), field.name, fun)]
2021-08-17 17:00:34 +08:00
for val, label, selected in field.iter_choices():
if self.value:
2023-09-03 21:17:55 +08:00
if str(val) == str(self.value):
2021-08-17 17:00:34 +08:00
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>')
2023-12-11 13:25:07 +08:00
return Markup(''.join(html))
2021-08-17 17:00:34 +08:00
@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
2023-12-11 13:25:07 +08:00
return Markup('<option %s>%s</option>' % (html_params(**options), escape_html(label, quote=False)))
2021-08-17 17:00:34 +08:00
2023-09-03 21:17:55 +08:00
2021-08-17 17:00:34 +08:00
# json编辑框
class MyJsonIde(object):
def __call__(self, field, **kwargs):
2023-12-11 13:25:07 +08:00
return Markup('<pre><code>%s</code></pre>' % (field._value(),))
# return Markup('<pre><code>%s</code></pre>' % (field._value(),))
2021-08-17 17:00:34 +08:00
class MySelect2ManyWidget(widgets.Select):
extra_classes = None
2023-09-03 21:17:55 +08:00
def __init__(self, extra_classes=None, style=None, can_input=False):
self.extra_classes = extra_classes
self.style = style or u"width:250px"
2023-09-03 21:17:55 +08:00
self.can_input = can_input
return super(MySelect2ManyWidget, self).__init__()
2021-08-17 17:00:34 +08:00
from wtforms.fields.core import SelectField
2023-09-03 21:17:55 +08:00
2021-08-17 17:00:34 +08:00
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(','))
2023-09-03 21:17:55 +08:00
self.data = [x for x in self.data if x]
2021-08-17 17:00:34 +08:00
# print(self.data)
else:
2023-09-03 21:17:55 +08:00
self.data = None
2021-08-17 17:00:34 +08:00
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
2023-09-03 21:17:55 +08:00
2021-08-17 17:00:34 +08:00
class MySearchWidget(FormWidget):
template = "appbuilder/general/widgets/search.html"
filters = None
def __init__(self, **kwargs):
self.filters = kwargs.get("filters")
2023-09-03 21:17:55 +08:00
self.help_url = kwargs.get("help_url", '')
2021-08-17 17:00:34 +08:00
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)