"""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 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 HTMLString,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 HTMLString('
%s
' % (self.code,)) else: return HTMLString('
%s
' % (field._value(),)) # return HTMLString('
%s
' % (field._value(),)) from wtforms import widgets class MyBS3TextAreaFieldWidget(widgets.TextArea): def __init__(self, rows=3,readonly=0): self.rows=rows self.readonly = readonly 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): self.value=value self.readonly = readonly 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): 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 # @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 = ['''') return HTMLString(''.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 HTMLString('' % (html_params(**options), escape_html(label, quote=False))) # json编辑框 class MyJsonIde(object): def __call__(self, field, **kwargs): return HTMLString('
%s
' % (field._value(),)) # return HTMLString('
%s
' % (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(',')) # 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)