# -*- encoding: utf-8 -*- """ @File : forms.py @Time : 2020/1/3 11:14 @Author : chise @Email : chise123@live.com @Software: PyCharm @info :simpleui自定义表单 """ from django import forms import uuid from django.core import validators from django.core.exceptions import ValidationError # Provide this import for backwards compatibility. from django.core.validators import EMPTY_VALUES # NOQA from django.forms.boundfield import BoundField from django.forms.forms import DeclarativeFieldsMetaclass, BaseForm from django.forms.utils import from_current_timezone, to_current_timezone from django.forms.widgets import ( FILE_INPUT_CONTRADICTION, CheckboxInput, ClearableFileInput, DateInput, DateTimeInput, EmailInput, FileInput, HiddenInput, MultipleHiddenInput, NullBooleanSelect, NumberInput, Select, SelectMultiple, SplitDateTimeWidget, SplitHiddenDateTimeWidget, TextInput, TimeInput, URLInput, ) from django.utils import formats from django.utils.dateparse import parse_duration from django.utils.duration import duration_string from django.utils.ipv6 import clean_ipv6_address from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _, ngettext_lazy import copy from django.core.exceptions import NON_FIELD_ERRORS, ValidationError # BoundField is imported for backwards compatibility in Django 1.9 from django.forms.boundfield import BoundField # NOQA from django.forms.fields import Field, FileField # pretty_name is imported for backwards compatibility in Django 1.9 from django.forms.utils import ErrorDict, ErrorList, pretty_name # NOQA from django.forms.widgets import Media, MediaDefiningClass from django.utils.functional import cached_property from django.utils.html import conditional_escape, html_safe from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from widgets import * class SimpleForm(BaseForm, metaclass=DeclarativeFieldsMetaclass): def get_vue_app_js(self,app_id): """ 将该方法需要的js渲染进去 :return: """ base_vue_app=""" """ data={} for name, field in self.fields.items(): data[name] = '' data.update(self.data) data_s="" for key,value in data.items(): data_s+="%(key)s:'%(value)s'"%{ 'key':key, 'value':value }+',' return base_vue_app %{"app_name":app_id,"data":data_s} def submit_button(self): """ 渲染模板增加submit格式 :return: """ # return '' pass def as_element(self): "Return this form rendered as HTML s -- excluding the
." x= self._html_output( normal_row='
%(label)s %(field)s%(help_text)s
', error_row='%s', row_ender='', help_text_html=' %s', errors_on_separate_row=True,flag=True ) return x def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row,flag=False): "Output HTML. Used by as_table(), as_ul(), as_p()." top_errors = self.non_field_errors() # Errors that should be displayed above all fields. output, hidden_fields = [], [] for name, field in self.fields.items(): html_class_attr = '' bf = self[name] if flag: bf.field.widget.flag=True bf_errors = self.error_class(bf.errors) if bf.is_hidden: if bf_errors: top_errors.extend( [_('(Hidden field %(name)s) %(error)s') % {'name': name, 'error': str(e)} for e in bf_errors]) hidden_fields.append(str(bf)) else: # Create a 'class="..."' attribute if the row should have any # CSS classes applied. css_classes = bf.css_classes() if css_classes: html_class_attr = ' class="%s"' % css_classes if errors_on_separate_row and bf_errors: output.append(error_row % str(bf_errors)) if bf.label: label = conditional_escape(bf.label) label = bf.label_tag(label) or '' else: label = '' if field.help_text: help_text = help_text_html % field.help_text else: help_text = '' output.append(normal_row % { 'errors': bf_errors, 'label': label, 'field': bf, 'help_text': help_text, 'html_class_attr': html_class_attr, 'css_classes': css_classes, 'field_name': bf.html_name, }) if top_errors: output.insert(0, error_row % top_errors) if hidden_fields: # Insert any hidden fields in the last row. str_hidden = ''.join(hidden_fields) if output: last_row = output[-1] # Chop off the trailing row_ender (e.g. '') and # insert the hidden fields. if not last_row.endswith(row_ender): # This can happen in the as_p() case (and possibly others # that users write): if there are only top errors, we may # not be able to conscript the last row for our purposes, # so insert a new, empty row. last_row = (normal_row % { 'errors': '', 'label': '', 'field': '', 'help_text': '', 'html_class_attr': html_class_attr, 'css_classes': '', 'field_name': '', }) output.append(last_row) output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender else: # If there aren't any rows in the output, just append the # hidden fields. output.append(str_hidden) if flag: app_id = "x" + str(uuid.uuid4())[0:5] output.insert(0, "
" %app_id) output.append('
') output.append(self.get_vue_app_js(app_id)) return mark_safe('\n'.join(output)) class SCharField(forms.CharField): widget = STextInput class SIntegerField(forms.IntegerField): def widget_attrs(self, widget): """ 解决max和min无法传递到widget的问题 """ attrs = super().widget_attrs(widget) if isinstance(widget, NumberInput) or isinstance(widget,SNumberInput): if self.min_value is not None: attrs['min'] = self.min_value if self.max_value is not None: attrs['max'] = self.max_value return attrs widget = SNumberInput class SEmailField(forms.EmailField): widget = SEmailInput class SURLField(forms.URLField): widget = SURLInput