Пример #1
0
class DataSearchForm(Form):
    q = StringField('Search terms', [Optional(), Length(1, 256)])
    start = DateTimeField('Start', [Optional()], format='%Y-%m-%d %H:%M:%S')
    end = DateTimeField('End', [Optional()], format='%Y-%m-%d %H:%M:%S')
Пример #2
0
class OtherWebsites(InsecureForm):
    name = TextField(_(u'name'), widget=partial(TextInput(), class_='input-small', placeholder=_(u'Name')))
    url = TextField(_(u'url'), widget=partial(TextInput(), class_='input-medium', placeholder=_(u'URL')),
                    validators=[Optional(), URL(require_tld=True)])
Пример #3
0
class ContactForm(FlaskForm):
    name = StringField(label="Name", validators=[DataRequired()])
    email = StringField("Email", validators=[Email(), DataRequired()])
    phone_number = StringField("Phone", validators=[Optional()])
    message = TextAreaField("Message", validators=[DataRequired()])
    submit = SubmitField("Submit")
Пример #4
0
class TagForm(FlaskForm):
    """
	标签
	"""
    tag = StringField('添加标签', validators=[Optional(), Length(0, 64)])
    submit = SubmitField('提交')
Пример #5
0
class ModuleServiceForm(FlaskForm):
    """Subform for services"""
    module_service_id = HiddenField('Service-ID', validators=[DataRequired()])
    module_service_name = HiddenField('Service', validators=[Optional()])
Пример #6
0
class RoutineAdmin(ModelView):
    inline_models = [(Schedule,
                      dict(form_args=dict(id=dict(validators=[Optional()]))))]
Пример #7
0
class AddScanJobForm(Form):

    type_hint1 = HintField(label="",
                           macro='deadline_hint',
                           depends_on=('type', 'normal'))

    type = RadioField(label=_("Type"),
                      choices=[('normal', _("Regular shipment"))],
                      validators=[InputRequired()],
                      default='normal')

    type_hint = HintField(label="",
                          macro='express_shipment_hint',
                          depends_on=('type', 'express'))

    dispatch_date_normal = SelectField(label=_("Dispatch date"),
                                       choices=[],
                                       depends_on=('type', 'normal'),
                                       validators=[InputRequired()],
                                       coerce=coerce_date)

    dispatch_date_express = DateField(
        label=_("Dispatch date"),
        depends_on=('type', 'express'),
        validators=[
            InputRequired(),
            DateRange(min=date.today, message=_("Date can't be in the past."))
        ],
        default=date.today)

    dispatch_boxes = IntegerField(
        label=_("Boxes"),
        fieldset=_("Dispatch to the tax office"),
        validators=[
            If(lambda form, field: form.type.data == 'normal',
               NumberRange(min=1)),
            If(lambda form, field: form.type.data != 'normal',
               Chain([Optional(), NumberRange(min=0)])),
        ],
        render_kw={
            'size': 3,
            'clear': False
        },
    )
    dispatch_tax_forms_older = IntegerField(
        label=_("Tax forms (older)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_last_year = IntegerField(
        label=_("Tax forms (previous year)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_current_year = IntegerField(
        label=_("Tax forms"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_single_documents = IntegerField(
        label=_("Single documents"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 3},
    )
    dispatch_note = TextAreaField(
        label=_("Note"),
        fieldset=_("Dispatch to the tax office"),
        render_kw={'rows': 5},
    )

    dispatch_cantonal_tax_office = IntegerField(
        label=_("Headquarters"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 6,
            'clear': False
        },
    )
    dispatch_cantonal_scan_center = IntegerField(
        label=_("Scan center"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 6,
            'clear': False
        },
    )

    @property
    def municipality_id(self):
        return self.request.identity.groupid or None

    @property
    def dispatch_date(self):
        if self.type.data == 'express':
            return self.dispatch_date_express.data
        return self.dispatch_date_normal.data

    def dispatch_dates(self, after):
        query = self.request.session.query(PickupDate.date.label('date'))
        query = query.filter(
            PickupDate.municipality_id == self.municipality_id)
        query = query.filter(PickupDate.date > after)
        query = query.order_by(PickupDate.date)
        return [r.date for r in query]

    @property
    def return_date(self):
        if self.type.data == 'express':
            return None
        return (self.dispatch_dates(self.dispatch_date) or [None])[0]

    def update_labels(self):
        year = date.today().year
        self.dispatch_tax_forms_older.label.text = _(
            "Tax forms until ${year}", mapping={'year': year - 2})
        self.dispatch_tax_forms_last_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year - 1})
        self.dispatch_tax_forms_current_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year})

    def on_request(self):
        # Shipment types
        if self.request.has_role('editor'):
            self.type.choices = [('normal', _("Regular shipment")),
                                 ('express', _("Express shipment"))]

        # Dispatch dates
        self.dispatch_date_normal.choices = [
            (r, f"{r:%d.%m.%Y}") for r in self.dispatch_dates(date.today())
        ]

        # Labels
        self.update_labels()

    def update_model(self, model):
        model.municipality_id = self.request.identity.groupid
        model.type = self.type.data
        model.dispatch_date = self.dispatch_date
        model.return_date = self.return_date
        for name in (
                'dispatch_boxes',
                'dispatch_tax_forms_current_year',
                'dispatch_tax_forms_last_year',
                'dispatch_tax_forms_older',
                'dispatch_single_documents',
                'dispatch_note',
                'dispatch_cantonal_tax_office',
                'dispatch_cantonal_scan_center',
        ):
            setattr(model, name, getattr(self, name).data)
Пример #8
0
class MapForm(FlaskForm):
    title = StringField('Titel',
                        description="Titel im Viewer",
                        validators=[DataRequired()])
    name = StringField('Name',
                       description="Name für Permalink",
                       validators=[DataRequired()])
    description = TextAreaField('Beschreibung', validators=[DataRequired()])
    responsible = SelectField(
        'Verantwortlicher',
        coerce=int,
        validators=[DataRequired(message="Kein Verantwortlicher ausgewählt")])
    sublayers = FieldList(FormField(MapLayerForm))
    layer = SelectField('Layer', coerce=int, validators=[Optional()])
    background_layer = SelectField('Default BackgroundLayer',
                                   coerce=int,
                                   validators=[Optional()])
    initial_extent = StringField(
        'Extent',
        validators=[
            DataRequired(),
            Regexp(
                r'\d+(\.\d+)?,\s*\d+(\.\d+)?,\s*\d+(\.\d+)?,\s*\d+(\.\d+)?',
                message="Extent nicht im Format <minx>,<miny>,<maxx>,<maxy>")
        ])
    initial_scale = IntegerField(
        'Massstab',
        validators=[
            Optional(),
            NumberRange(min=1, message="Massstab muss grösser 0 sein")
        ])
    thumbnail_file = FileField('Vorschaubild')
    thumbnail_present = False
    remove_thumbnail = BooleanField('Vorhandenes Vorschaubild entfernen')
    permissions = FieldList(FormField(PermissionForm))
    role = SelectField('Rolle', coerce=int, validators=[Optional()])

    submit = SubmitField('Speichern')

    def __init__(self, config_models, **kwargs):
        """Constructor

        :param ConfigModels config_models: Helper for ORM models
        """
        self.config_models = config_models
        self.Map = self.config_models.model('map')

        # store any provided user object
        self.obj = kwargs.get('obj')

        super(MapForm, self).__init__(**kwargs)

    def validate_name(self, field):
        """Validate uniqueness of name"""
        # check if Map name exists
        session = self.config_models.session()
        query = session.query(self.Map).filter_by(name=field.data)
        if self.obj:
            # ignore current map
            query = query.filter(self.Map.gdi_oid != self.obj.gdi_oid)
        map_obj = query.first()
        session.close()

        if map_obj is not None:
            raise ValidationError(
                'Eine Map mit diesem Namen ist bereits vorhanden')
Пример #9
0
class EditUserProfile(Form):
  username = StringField('Username',
                         validators=[Optional(), Length(min=3, max=25)])
  email = StringField('Email',
                      validators=[Optional(), Email(), Length(min=6, max=40)])
  first_name = StringField('First Name',
                           validators=[Optional()])
  last_name = StringField('Last Name',
                          validators=[Optional()])

  old_password_confirm = PasswordField('Old Password',
                                       validators=[Optional(),
                                                   Length(min=6, max=40)])
  new_password = PasswordField('New Password',
                               validators=[Optional(), Length(min=6, max=40)])
  new_confirm = PasswordField('Verify New Password',
                              [Optional(),
                               EqualTo('new_password',
                                       message='Passwords must match')])

  def __init__(self, user_id, *args, **kwargs):
    super(EditUserProfile, self).__init__(*args, **kwargs)
    self.user = User.get_by_id(user_id)
    self.username.placeholder = "Username"
    self.email.placeholder = "Email Address"
    self.first_name.placeholder = "First Name"
    self.last_name.placeholder = "Last Name"

    if not request.method == 'POST':
      self.username.data = self.user.username
      self.email.data = self.user.email
      self.first_name.data = self.user.first_name
      self.last_name.data = self.user.last_name

  def validate(self):
    initial_validation = super(EditUserProfile, self).validate()
    if not initial_validation:
      return False
    valid = True

    # Reset Password Logic
    if self.old_password_confirm.data:
      if self.new_password.data:
        if self.new_confirm.data:
          if not self.user.check_password(self.old_password_confirm.data):
            self.old_password_confirm.errors.append('Old password '
                                                    'was incorrect')
            valid = False
          else:
            if not self.new_password.data == self.new_confirm.data:
              self.new_confirm.errors('Verify New Password field'
                                      ' does not match New Password Field')
              valid = False
        else:
          self.new_confirm.errors.append('Confirm Password Field was blank')
          valid = False

    if self.username.data:
      new_username = User.query.filter_by(
        username=self.username.data).first()
      if new_username and not (self.user.username == self.username.data):
        print self.user.username
        print self.username.data
        # Usernames should be unique
        self.username.errors.append('This username is already taken')
        valid = False
    if not self.user.first_name and not self.first_name.data:
      self.first_name.errors.append('First Name is required')
      valid = False
    if not self.user.last_name and not self.last_name.data:
      self.last_name.errors.append('Last Name is required')
      valid = False

    return valid

  def commit_updates(self):
    if self.new_password.data:
      self.user.set_password(self.new_password.data)
    if self.first_name.data:
      self.user.first_name = self.first_name.data
    if self.last_name.data:
      self.user.last_name = self.last_name.data
    if self.username.data:
      self.user.username = self.username.data
    if self.email.data:
      self.user.email = self.email.data
    self.user.save()
Пример #10
0
class EditPetForm(FlaskForm):
    """ Form for editing pets """

    photo_url = StringField("Photo URL", validators=[Optional(), url()])
    notes = StringField("Notes")
    available = BooleanField('Available for Adoption?')
Пример #11
0
class PermissionForm(FlaskForm):
    """Subform for permissions"""
    role_id = HiddenField('Rollen-ID', validators=[DataRequired()])
    role_name = HiddenField('Rolle', validators=[Optional()])
    read = BooleanField('Lesen')
Пример #12
0
class EditPetForm(FlaskForm):
    photo_url = StringField("Photo URL",
                            validators=[Optional(),
                                        URL(require_tld=True)])
    notes = TextAreaField("Notes", validators=[Optional()])
    available = BooleanField("Available")
Пример #13
0
class CsvToDatabaseForm(DynamicForm):
    # pylint: disable=E0211
    def all_db_items():
        return db.session.query(models.Database)

    name = StringField(
        _('Table Name'),
        description=_('Name of table to be created from csv data.'),
        validators=[DataRequired()],
        widget=BS3TextFieldWidget())
    csv_file = FileField(
        _('CSV File'),
        description=_('Select a CSV file to be uploaded to a database.'),
        validators=[
            FileRequired(),
            FileAllowed(['csv'], _('CSV Files Only!'))
        ])
    con = QuerySelectField(query_factory=all_db_items,
                           get_pk=lambda a: a.id,
                           get_label=lambda a: a.database_name)
    sep = StringField(
        _('Delimiter'),
        description=_('Delimiter used by CSV file (for whitespace use \s+).'),
        validators=[DataRequired()],
        widget=BS3TextFieldWidget())
    if_exists = SelectField(
        _('Table Exists'),
        description=_('If table exists do one of the following: '
                      'Fail (do nothing), Replace (drop and recreate table) '
                      'or Append (insert data).'),
        choices=[('fail', _('Fail')), ('replace', _('Replace')),
                 ('append', _('Append'))],
        validators=[DataRequired()])
    schema = StringField(
        _('Schema'),
        description=_('Specify a schema (if database flavour supports this).'),
        validators=[Optional()],
        widget=BS3TextFieldWidget(),
        filters=[lambda x: x or None])
    header = IntegerField(_('Header Row'),
                          description=_(
                              'Row containing the headers to use as '
                              'column names (0 is first line of data). '
                              'Leave empty if there is no header row.'),
                          validators=[Optional()],
                          widget=BS3TextFieldWidget(),
                          filters=[lambda x: x or None])
    index_col = IntegerField(_('Index Column'),
                             description=_(
                                 'Column to use as the row labels of the '
                                 'dataframe. Leave empty if no index column.'),
                             validators=[Optional(),
                                         NumberRange(0, 1E+20)],
                             widget=BS3TextFieldWidget(),
                             filters=[lambda x: x or None])
    mangle_dupe_cols = BooleanField(
        _('Mangle Duplicate Columns'),
        description=_('Specify duplicate columns as "X.0, X.1".'))
    skipinitialspace = BooleanField(
        _('Skip Initial Space'), description=_('Skip spaces after delimiter.'))
    skiprows = IntegerField(
        _('Skip Rows'),
        description=_('Number of rows to skip at start of file.'),
        validators=[Optional(), NumberRange(0, 1E+20)],
        widget=BS3TextFieldWidget(),
        filters=[lambda x: x or None])
    nrows = IntegerField(_('Rows to Read'),
                         description=_('Number of rows of file to read.'),
                         validators=[Optional(),
                                     NumberRange(0, 1E+20)],
                         widget=BS3TextFieldWidget(),
                         filters=[lambda x: x or None])
    skip_blank_lines = BooleanField(
        _('Skip Blank Lines'),
        description=_('Skip blank lines rather than interpreting them '
                      'as NaN values.'))
    parse_dates = BooleanField(_('Parse Dates'),
                               description=_('Parse date values.'))
    infer_datetime_format = BooleanField(
        _('Infer Datetime Format'),
        description=_('Use Pandas to interpret the datetime format '
                      'automatically.'))
    decimal = StringField(
        _('Decimal Character'),
        description=_('Character to interpret as decimal point.'),
        validators=[Optional()],
        widget=BS3TextFieldWidget(),
        filters=[lambda x: x or '.'])
    index = BooleanField(_('Dataframe Index'),
                         description=_('Write dataframe index as a column.'))
    index_label = StringField(
        _('Column Label(s)'),
        description=_('Column label for index column(s). If None is given '
                      'and Dataframe Index is True, Index Names are used.'),
        validators=[Optional()],
        widget=BS3TextFieldWidget(),
        filters=[lambda x: x or None])
Пример #14
0
class AddCupcakeForm(FlaskForm):

    flavor = StringField("Flavor", validators=[InputRequired()])
    size = StringField("Size", validators=[InputRequired()])
    rating = FloatField("Rating", validators=[InputRequired()])
    image = StringField("Image", validators=[Optional(), URL()])
Пример #15
0
class RegistrationFormForm(IndicoForm):
    _price_fields = ('currency', 'base_price')
    _registrant_notification_fields = ('notification_sender_address',
                                       'message_pending', 'message_unpaid',
                                       'message_complete')
    _manager_notification_fields = ('manager_notifications_enabled',
                                    'manager_notification_recipients')
    _special_fields = _price_fields + _registrant_notification_fields + _manager_notification_fields

    title = StringField(_("Title"), [DataRequired()],
                        description=_("The title of the registration form"))
    introduction = TextAreaField(
        _("Introduction"),
        description=
        _("Introduction to be displayed when filling out the registration form"
          ))
    contact_info = StringField(
        _("Contact info"),
        description=
        _("How registrants can get in touch with somebody for extra information"
          ))
    moderation_enabled = BooleanField(
        _("Moderated"),
        widget=SwitchWidget(),
        description=_("If enabled, registrations require manager approval"))
    require_login = BooleanField(
        _("Only logged-in users"),
        widget=SwitchWidget(),
        description=_("Users must be logged in to register"))
    require_user = BooleanField(
        _("Registrant must have account"),
        widget=SwitchWidget(),
        description=_(
            "Registrations emails must be associated with an Indico account"))
    limit_registrations = BooleanField(
        _("Limit registrations"),
        widget=SwitchWidget(),
        description=_("Whether there is a limit of registrations"))
    registration_limit = IntegerField(
        _("Capacity"), [
            HiddenUnless('limit_registrations'),
            DataRequired(),
            NumberRange(min=1)
        ],
        description=_("Maximum number of registrations"))
    modification_mode = IndicoEnumSelectField(
        _("Modification allowed"),
        enum=ModificationMode,
        description=_("Will users be able to modify their data? When?"))
    publish_registrations_enabled = BooleanField(
        _('Publish registrations'),
        widget=SwitchWidget(),
        description=_("Registrations from this form will be displayed in the "
                      "event page"))
    publish_registration_count = BooleanField(
        _("Publish number of registrations"),
        widget=SwitchWidget(),
        description=_("Number of registered participants will be displayed in "
                      "the event page"))
    publish_checkin_enabled = BooleanField(
        _('Publish check-in status'),
        widget=SwitchWidget(),
        description=_(
            "Check-in status will be shown publicly on the event page"))
    base_price = DecimalField(
        _('Registration fee'), [
            NumberRange(min=0, max=999999.99),
            Optional(), _check_if_payment_required
        ],
        filters=[lambda x: x if x is not None else 0],
        widget=NumberInput(step='0.01'),
        description=_("A fixed fee all users have to pay when registering."))
    currency = SelectField(_('Currency'), [DataRequired()],
                           description=_('The currency for new registrations'))
    notification_sender_address = StringField(_('Notification sender address'),
                                              [IndicoEmail()],
                                              filters=[lambda x: (x or None)])
    message_pending = TextAreaField(
        _("Message for pending registrations"),
        description=_("Text included in emails sent to pending registrations"))
    message_unpaid = TextAreaField(
        _("Message for unpaid registrations"),
        description=_("Text included in emails sent to unpaid registrations"))
    message_complete = TextAreaField(
        _("Message for complete registrations"),
        description=_(
            "Text included in emails sent to complete registrations"))
    manager_notifications_enabled = BooleanField(
        _('Enabled'),
        widget=SwitchWidget(),
        description=_("Enable notifications to managers about registrations"))
    manager_notification_recipients = EmailListField(
        _('List of recipients'), [
            HiddenUnless('manager_notifications_enabled', preserve_data=True),
            DataRequired()
        ],
        description=_("Email addresses that will receive notifications"))

    def __init__(self, *args, **kwargs):
        self.event = kwargs.pop('event')
        super(IndicoForm, self).__init__(*args, **kwargs)
        self._set_currencies()
        self.notification_sender_address.description = _(
            'Email address set as the sender of all '
            'notifications sent to users. If empty, '
            'then {0} is used.'.format(config.NO_REPLY_EMAIL))

    def _set_currencies(self):
        currencies = [(c['code'], '{0[code]} ({0[name]})'.format(c))
                      for c in payment_settings.get('currencies')]
        self.currency.choices = sorted(currencies, key=lambda x: x[1].lower())
Пример #16
0
class ProfileForm(FlaskForm):
    logotype = FileField('Logotype', [Optional()])
    first_name = StringField('First name', [Optional(), Length(max=32)])
    last_name = StringField('Last name', [Optional(), Length(max=32)])
    about = MarkdownField('About', [Optional()])
    submit = SubmitField('Save')
Пример #17
0
class ActivityAdmin(ModelView):
    inline_models = [(LocationActivity,
                      dict(form_args=dict(id=dict(validators=[Optional()]))))]
Пример #18
0
class EditWeaponForm(FlaskForm):
    """Form to edit Weapon"""

    name = StringField(
        "Name",
        validators=[
            InputRequired(),
            Length(
                min=1,
                max=50,
                message="Name must be at least 1 character and not over 50.")
        ])
    image_url = SelectField("Icon Image",
                            choices=[("static/weapon01.png", "Sword"),
                                     ("static/weapon02.png", "Battle Axe"),
                                     ("static/weapon03.png", "Bow")])
    damage = StringField("Damage",
                         validators=[
                             Length(
                                 min=0,
                                 max=25,
                                 message="Damage must be under 25 characters.")
                         ])
    weapon_type = StringField(
        "Weapon Type",
        validators=[
            Length(min=0,
                   max=25,
                   message="Weapon type must be under 25 characters.")
        ])
    damage_type = StringField(
        "Damage Type",
        validators=[
            Length(min=0,
                   max=25,
                   message="Damage type must be under 25 characters.")
        ])
    weapon_range = TextField(
        "Weapon Range",
        validators=[
            Length(min=0,
                   max=25,
                   message="Weapon range must be under 25 characters.")
        ])
    weight = DecimalField("Weight", validators=[Optional()])
    condition = StringField(
        "Condition",
        validators=[
            Length(min=0,
                   max=25,
                   message="Condition must be under 25 characters.")
        ])
    rarity = StringField("Rarity",
                         validators=[
                             Length(
                                 min=0,
                                 max=25,
                                 message="Rarity must be under 25 characters.")
                         ])
    description = TextField("Description", widget=TextArea())
    notes = TextField("Notes", widget=TextArea())
Пример #19
0
class EditScanJobForm(Form):

    callout = _("Fill in until 17.00 o'clock the evening before.")

    dispatch_boxes = IntegerField(
        label=_("Boxes"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 3,
            'clear': False
        },
    )
    dispatch_tax_forms_older = IntegerField(
        label=_("Tax forms (older)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_last_year = IntegerField(
        label=_("Tax forms (previous year)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_current_year = IntegerField(
        label=_("Tax forms"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_single_documents = IntegerField(
        label=_("Single documents"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 3},
    )
    dispatch_note = TextAreaField(
        label=_("Note"),
        fieldset=_("Dispatch to the tax office"),
        render_kw={'rows': 5},
    )

    dispatch_cantonal_tax_office = IntegerField(
        label=_("Headquarters"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 6,
            'clear': False
        },
    )
    dispatch_cantonal_scan_center = IntegerField(
        label=_("Scan center"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 6},
    )

    def update_labels(self):
        year = date.today().year
        self.dispatch_tax_forms_older.label.text = _(
            "Tax forms until ${year}", mapping={'year': year - 2})
        self.dispatch_tax_forms_last_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year - 1})
        self.dispatch_tax_forms_current_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year})

    def on_request(self):
        self.update_labels()

    def update_model(self, model):
        for name in (
                'dispatch_boxes',
                'dispatch_tax_forms_current_year',
                'dispatch_tax_forms_last_year',
                'dispatch_tax_forms_older',
                'dispatch_single_documents',
                'dispatch_note',
                'dispatch_cantonal_tax_office',
                'dispatch_cantonal_scan_center',
        ):
            setattr(model, name, getattr(self, name).data)

    def apply_model(self, model):
        for name in (
                'dispatch_boxes',
                'dispatch_tax_forms_current_year',
                'dispatch_tax_forms_last_year',
                'dispatch_tax_forms_older',
                'dispatch_single_documents',
                'dispatch_note',
                'dispatch_cantonal_tax_office',
                'dispatch_cantonal_scan_center',
        ):
            getattr(self, name).data = getattr(model, name)

        self.callout = _(
            "Fill in until 17.00 o'clock the evening before ${date}.",
            mapping={'date': f"{model.dispatch_date:%d.%m.%Y}"})
Пример #20
0
class AddCharacterForm(FlaskForm):
    """Form to add new character"""

    name = StringField(
        "Name",
        validators=[
            InputRequired(),
            Length(
                min=1,
                max=50,
                message="Name must be at least 1 character and not over 50.")
        ])
    portrait_url = SelectField("Portrait",
                               choices=[("static/portrait01.png", "Knight"),
                                        ("static/portrait02.png", "Wizard"),
                                        ("static/portrait03.png",
                                         "Elf Archer"),
                                        ("static/portrait04.png", "Halfling")])
    icon = SelectField("Icon Image",
                       choices=[("static/charactericon01.png", "Icon 1"),
                                ("static/charactericon02.png", "Icon 2"),
                                ("static/charactericon03.png", "Icon 3"),
                                ("static/charactericon04.png", "Icon 4"),
                                ("static/charactericon05.png", "Icon 5"),
                                ("static/charactericon06.png", "Icon 6")])
    class_name = StringField(
        "Class",
        validators=[
            InputRequired(),
            Length(min=1,
                   max=25,
                   message="URL must be at least 1 character and not over 25.")
        ])
    race = StringField(
        "Race",
        validators=[
            InputRequired(),
            Length(
                min=1,
                max=25,
                message="Race must be at least 1 character and not over 25.")
        ])
    level = IntegerField("Level", validators=[Optional()])
    alignment = StringField(
        "Alignment",
        validators=[
            Length(min=0,
                   max=25,
                   message="Alignment must be under 25 characters.")
        ])
    proficiencies = TextField("Proficiencies")
    statuses = StringField(
        "Statuses",
        validators=[
            Length(min=0,
                   max=50,
                   message="Statuses must be under 50 characters.")
        ])
    age = StringField("Age",
                      validators=[
                          Length(min=0,
                                 max=50,
                                 message="Age must be under 25 characters.")
                      ])
    traits = TextField("Traits")
    languages = TextField("Languages")
    stats = TextField("Stats", widget=TextArea(), validators=[InputRequired()])
    backstory = TextField("Backstory", widget=TextArea())
    notes = TextField("Notes", widget=TextArea())
    hirelings = TextField("List of Hirelings", widget=TextArea())
    pets_minions = TextField("List of Pets and Minions", widget=TextArea())
Пример #21
0
class UnrestrictedScanJobForm(Form):

    municipality_id = SelectField(label=_("Municipality"),
                                  choices=[],
                                  validators=[InputRequired()])

    type = RadioField(label=_("Type"),
                      choices=[('normal', _("Regular shipment")),
                               ('express', _("Express shipment"))],
                      validators=[InputRequired()],
                      default='normal')

    dispatch_date = DateField(
        label=_("Dispatch date"),
        validators=[InputRequired()],
        default=date.today,
    )

    dispatch_date_hint = PreviewField(
        label=_("Regular dispatch dates"),
        fields=('municipality_id', ),
        events=('change', ),
        url=lambda meta: meta.request.link(meta.request.app.principal,
                                           name='dispatch-dates'))

    dispatch_boxes = IntegerField(
        label=_("Boxes"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 3,
            'clear': False
        },
    )
    dispatch_tax_forms_older = IntegerField(
        label=_("Tax forms (older)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_last_year = IntegerField(
        label=_("Tax forms (previous year)"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_tax_forms_current_year = IntegerField(
        label=_("Tax forms"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    dispatch_single_documents = IntegerField(
        label=_("Single documents"),
        fieldset=_("Dispatch to the tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 3},
    )
    dispatch_note = TextAreaField(
        label=_("Note"),
        fieldset=_("Dispatch to the tax office"),
        render_kw={'rows': 5},
    )

    dispatch_cantonal_tax_office = IntegerField(
        label=_("Headquarters"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 6,
            'clear': False
        },
    )
    dispatch_cantonal_scan_center = IntegerField(
        label=_("Scan center"),
        fieldset=_("Dispatch to the cantonal tax office"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 6},
    )

    return_date = DateField(label=_("Return date"),
                            fieldset=_("Return to the municipality"),
                            validators=[Optional()])

    return_boxes = IntegerField(
        label=_("Boxes"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 3,
            'clear': False
        },
    )
    return_tax_forms_older = IntegerField(
        label=_("Tax forms (older)"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    return_tax_forms_last_year = IntegerField(
        label=_("Tax forms (previous year)"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    return_tax_forms_current_year = IntegerField(
        label=_("Tax forms"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    return_single_documents = IntegerField(
        label=_("Single documents"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 3},
    )
    return_unscanned_tax_forms_older = IntegerField(
        label=_("Unscanned tax forms (older)"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'offset': 3,
            'size': 2,
            'clear': False
        },
    )
    return_unscanned_tax_forms_last_year = IntegerField(
        label=_("Unscanned tax forms (previous year)"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    return_unscanned_tax_forms_current_year = IntegerField(
        label=_("Unscanned tax forms"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={
            'size': 2,
            'clear': False
        },
    )
    return_unscanned_single_documents = IntegerField(
        label=_("Unscanned single documents"),
        fieldset=_("Return to the municipality"),
        validators=[Optional(), NumberRange(min=0)],
        render_kw={'size': 3},
    )
    return_note = TextAreaField(
        label=_("Note"),
        fieldset=_("Return to the municipality"),
        render_kw={'rows': 5},
    )

    def update_labels(self):
        year = date.today().year
        self.dispatch_tax_forms_older.label.text = _(
            "Tax forms until ${year}", mapping={'year': year - 2})
        self.dispatch_tax_forms_last_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year - 1})
        self.dispatch_tax_forms_current_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year})
        self.return_tax_forms_older.label.text = _("Tax forms until ${year}",
                                                   mapping={'year': year - 2})
        self.return_tax_forms_last_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year - 1})
        self.return_tax_forms_current_year.label.text = _(
            "Tax forms ${year}", mapping={'year': year})
        self.return_unscanned_tax_forms_older.label.text = _(
            "Unscanned tax forms until ${year}", mapping={'year': year - 2})
        self.return_unscanned_tax_forms_last_year.label.text = _(
            "Unscanned tax forms ${year}", mapping={'year': year - 1})
        self.return_unscanned_tax_forms_current_year.label.text = _(
            "Unscanned tax forms ${year}", mapping={'year': year})

    def on_request(self):
        query = self.request.session.query(
            Municipality.id.label('id'),
            Municipality.name.label('name'),
            Municipality.meta['bfs_number'].label('bfs_number'),
        )
        query = query.order_by(unaccent(Municipality.name))
        self.municipality_id.choices = [
            (r.id.hex, f"{r.name} ({r.bfs_number})") for r in query
        ]

        self.update_labels()

    def update_model(self, model):
        for name in (
                'municipality_id',
                'type',
                'dispatch_date',
                'dispatch_boxes',
                'dispatch_tax_forms_current_year',
                'dispatch_tax_forms_last_year',
                'dispatch_tax_forms_older',
                'dispatch_single_documents',
                'dispatch_note',
                'dispatch_cantonal_tax_office',
                'dispatch_cantonal_scan_center',
                'return_boxes',
                'return_tax_forms_current_year',
                'return_tax_forms_last_year',
                'return_tax_forms_older',
                'return_single_documents',
                'return_date',
                'return_unscanned_tax_forms_current_year',
                'return_unscanned_tax_forms_last_year',
                'return_unscanned_tax_forms_older',
                'return_unscanned_single_documents',
                'return_note',
        ):
            setattr(model, name, getattr(self, name).data)

    def apply_model(self, model):
        self.municipality_id.data = model.municipality_id.hex
        for name in (
                'type',
                'dispatch_date',
                'dispatch_boxes',
                'dispatch_tax_forms_current_year',
                'dispatch_tax_forms_last_year',
                'dispatch_tax_forms_older',
                'dispatch_single_documents',
                'dispatch_note',
                'dispatch_cantonal_tax_office',
                'dispatch_cantonal_scan_center',
                'return_date',
                'return_boxes',
                'return_tax_forms_current_year',
                'return_tax_forms_last_year',
                'return_tax_forms_older',
                'return_single_documents',
                'return_unscanned_tax_forms_current_year',
                'return_unscanned_tax_forms_last_year',
                'return_unscanned_tax_forms_older',
                'return_unscanned_single_documents',
                'return_note',
        ):
            getattr(self, name).data = getattr(model, name)
Пример #22
0
class MemberSecarchDob(FlaskForm):
    """Search for members by birth month form"""
    dob = DateField('Birthday Month', format='%m', validators=[Optional()])

    search1 = SubmitField('Birthday Month Search')
Пример #23
0
class EditPetForm(FlaskForm):
    photo_url = StringField("Photo URL", validators=[Optional(), URL()]),
    notes = StringField("Notes", validators=[Optional()])
    available = BooleanField("This pet is available for adoption.")
Пример #24
0
class EditNaturalPersonForm(FlaskForm):
    name = StringField('Name')
    rg = StringField('RG', validators=[Optional(), validate_rg])
    submit_details = SubmitField('Update')
Пример #25
0
class DataProductForm(FlaskForm):
    """Subform for data products"""
    data_product_id = HiddenField('DataProduct-ID', validators=[DataRequired()])
    data_product_name = HiddenField('DataProduct', validators=[Optional()])
Пример #26
0
class RegistrationForm(Form):

    name = StringField(
        label='Name',
        validators=[
            Required(),
            Length(max=35),
        ],
        render_kw={
            'placeholder': 'e.g. Sergey',
        },
    )
    surname = StringField(
        label='Surname',
        validators=[
            Required(),
            Length(max=35),
        ],
        render_kw={
            'placeholder': 'e.g. Brin',
        },
    )
    nickname = StringField(
        label='Nickname',
        validators=[
            Length(max=45),
        ],
        render_kw={
            'placeholder': 'e.g. SuperBrin',
        },
    )
    email = StringField(
        label='Email',
        validators=[
            Required(),
            Email(),
        ],
        render_kw={
            'placeholder': '*****@*****.**',
        },
    )
    phone = StringField(
        label='Phone number',
        validators=[
            Length(max=20),
        ],
        render_kw={
            'placeholder': '0931234567',
        },
    )
    gplus = StringField(
        label='Google+ id',
        validators=[
            Required(),
        ],
        render_kw={
            'placeholder': 'e.g. 1000000000042',
        },
    )
    www = StringField(
        label='Website URL',
        validators=[
            Optional(),
            Length(max=100),
            URL(),
        ],
        render_kw={
            'placeholder': 'Start with http://',
        },
    )
    hometown = StringField(
        label='City',
        validators=[
            Required(),
            Length(max=30),
        ],
        render_kw={
            'placeholder': 'e.g. Mountain View',
        },
    )
    company = StringField(
        label='Company',
        validators=[
            Length(max=64),
        ],
        render_kw={
            'placeholder': 'e.g. Google',
        },
    )
    position = StringField(
        label='Position',
        validators=[
            Length(max=64),
        ],
        render_kw={
            'placeholder': 'e.g. Cofounder',
        },
    )
    experience_level = SelectField(
        label='Experience level',
        choices=[(c, c.capitalize()) for c in EXPERIENCE_CHOICES],
    )
    experience_desc = TextAreaField(
        label='Experience description',
        render_kw={
            'placeholder':
            ('e.g. Software developer particularly interested in Java '
             'technologies and Google applications. Worked in various '
             'countries: Ukraine, USA, Poland. '
             'Have great ability to work remotely, high mobility, '
             'sense of humor.'),
        },
    )
    interests = TextAreaField(
        label='Interests',
        render_kw={
            'placeholder': 'e.g. Google, Android, Chrome',
        },
    )
    events_visited = StringField(
        label='Events visited',
        render_kw={
            'placeholder': ('e.g. IO Extended 2015, GDG DevFest, hackathons, '
                            'code labs, Study Jams or WTM events'),
        },
    )
    english_knowledge = SelectField(
        label='English knowledge',
        choices=[(c, c.capitalize()) for c in ENGLISH_CHOICES],
    )
    t_shirt_size = SelectField(
        label='T-Shirt size',
        choices=[(c.lower(), c) for c in TSHIRT_CHOICES],
    )
    gender = SelectField(
        label='Gender',
        choices=[(c, c.capitalize()) for c in GENDER_CHOICES],
        validators=[Required()],
        widget=InlineWidget(prefix_label=False),
        option_widget=RadioInput(),
    )
    additional_info = TextAreaField(
        label='Comments',
        render_kw={
            'placeholder': 'If you have something to say us, leave it here =)',
        },
    )

    def __init__(self, hidden=None, *args, **kwargs):
        if hidden is None:
            hidden = []

        super(RegistrationForm, self).__init__(*args, **kwargs)

        for name in hidden:
            field = getattr(self, name, None)
            if field and field.flags.required:
                # Hiding required field might cause db operational error
                # Hence do not allow hiding required fields
                logger.error('Trying to hide required field %s', name)
                raise ValueError('Field {} is required'.format(name))
            delattr(self, name)
Пример #27
0
class ProjectForm(Form):
    name = TextField(_(u'full name'), description=[_(u'E.g. French Data Network')],
                     validators=[DataRequired(), Length(min=2), Unique(ISP, ISP.name)])
    shortname = TextField(_(u'short name'), description=[_(u'E.g. FDN')],
                          validators=[Optional(), Length(min=2, max=15), Unique(ISP, ISP.shortname)])
    description = TextField(_(u'description'), description=[None, _(u'Short text describing the project')])
    logo_url = TextField(_(u'logo url'), validators=[Optional(), URL(require_tld=True)])
    website = TextField(_(u'website'), validators=[Optional(), URL(require_tld=True)])
    other_websites = FieldList(MyFormField(OtherWebsites, widget=partial(InputListWidget(), class_='formfield')),
                               min_entries=1, widget=InputListWidget(),
                               description=[None, _(u'Additional websites that you host (e.g. wiki, etherpad...)')])
    contact_email = TextField(_(u'contact email'), validators=[Optional(), Email()],
                              description=[None, _(u'General contact email address')])
    main_ml = TextField(_(u'main mailing list'), validators=[Optional(), Email()],
                        description=[None, _(u'Address of your main mailing list')])
    creation_date = DateField(_(u'creation date'), validators=[Optional()], widget=partial(TextInput(), placeholder=_(u'YYYY-mm-dd')),
                              description=[None, _(u'Date at which the legal structure for your project was created')])
    chatrooms = FieldList(TextField(_(u'chatrooms')), min_entries=1, widget=InputListWidget(),
                          description=[None, _(u'In URI form, e.g. <code>irc://irc.isp.net/#isp</code> or ' +
                          '<code>xmpp:[email protected]?join</code>')])
    covered_areas = FieldList(MyFormField(CoveredArea, _('Covered Areas'), widget=partial(InputListWidget(), class_='formfield')),
                              min_entries=1, widget=InputListWidget(),
                              description=[None, _(u'Descriptive name of the covered areas and technologies deployed')])
    latitude = DecimalField(_(u'latitude'), validators=[Optional(), NumberRange(min=-90, max=90)],
                            description=[None, _(u'Coordinates of your registered office or usual meeting location. '
                            '<strong>Required in order to appear on the map.</strong>')])
    longitude = DecimalField(_(u'longitude'), validators=[Optional(), NumberRange(min=-180, max=180)])
    step = SelectField(_(u'progress step'), choices=STEP_CHOICES, coerce=int)
    member_count = IntegerField(_(u'members'), validators=[Optional(), NumberRange(min=0)],
                                description=[None, _('Number of members')])
    subscriber_count = IntegerField(_(u'subscribers'), validators=[Optional(), NumberRange(min=0)],
                                    description=[None, _('Number of subscribers to an internet access')])

    tech_email = TextField(_('Email'), validators=[Email(), DataRequired()], description=[None,
                            _('Technical contact, in case of problems with your submission')])

    def validate(self, *args, **kwargs):
        r = super(ProjectForm, self).validate(*args, **kwargs)
        if (self.latitude.data is None) != (self.longitude.data is None):
            self._fields['longitude'].errors += [_(u'You must fill both fields')]
            r = False
        return r

    def validate_covered_areas(self, field):
        if len(filter(lambda e: e['name'], field.data)) == 0:
            # not printed, whatever..
            raise ValidationError(_(u'You must specify at least one area'))

        geojson_size = sum([len(ca.area.raw_data[0]) for ca in self.covered_areas if ca.area.raw_data])
        max_size = current_app.config['ISP_FORM_GEOJSON_MAX_SIZE_TOTAL']
        if geojson_size > max_size:
            # TODO: XXX This is not printed !
            raise ValidationError(gettext(u'The size of all GeoJSON data combined must not exceed %(max_size)s',
                                          max_size=filesize_fmt(max_size)))

    def to_json(self, json=None):
        if json is None:
            json = {}

        json['name'] = self.name.data

        def optstr(k, v):
            if k in json or v:
                json[k] = v

        def optlist(k, v):
            if k in json or len(v):
                json[k] = v

        def transform_covered_areas(cas):
            for ca in cas:
                if not ca['name']:
                    continue
                if 'area' in ca and ca['area'] is None:
                    del ca['area']
                yield ca

        optstr('shortname', self.shortname.data)
        optstr('description', self.description.data)
        optstr('logoURL', self.logo_url.data)
        optstr('website', self.website.data)
        optstr('otherWebsites', dict(((w['name'], w['url']) for w in self.other_websites.data if w['name'])))
        optstr('email', self.contact_email.data)
        optstr('mainMailingList', self.main_ml.data)
        optstr('creationDate', self.creation_date.data.isoformat() if self.creation_date.data else None)
        optstr('progressStatus', self.step.data)
        optstr('memberCount', self.member_count.data)
        optstr('subscriberCount', self.subscriber_count.data)
        optlist('chatrooms', filter(bool, self.chatrooms.data))  # remove empty strings
        optstr('coordinates', {'latitude': self.latitude.data, 'longitude': self.longitude.data}
              if self.latitude.data else {})
        optlist('coveredAreas', list(transform_covered_areas(self.covered_areas.data)))
        return json

    @classmethod
    def edit_json(cls, isp):
        json = isp.json
        obj = type('abject', (object,), {})()

        def set_attr(attr, itemk=None, d=json):
            if itemk is None:
                itemk = attr
            if itemk in d:
                setattr(obj, attr, d[itemk])
        set_attr('name')
        set_attr('shortname')
        set_attr('description')
        set_attr('logo_url', 'logoURL')
        set_attr('website')
        set_attr('contact_email', 'email')
        set_attr('main_ml', 'mainMailingList')
        set_attr('creation_date', 'creationDate')
        if hasattr(obj, 'creation_date'):
            obj.creation_date = ISP.str2date(obj.creation_date)
        set_attr('step', 'progressStatus')
        set_attr('member_count', 'memberCount')
        set_attr('subscriber_count', 'subscriberCount')
        set_attr('chatrooms', 'chatrooms')
        if 'coordinates' in json:
            set_attr('latitude', d=json['coordinates'])
            set_attr('longitude', d=json['coordinates'])
        if 'otherWebsites' in json:
            setattr(obj, 'other_websites', [{'name': n, 'url': w} for n, w in json['otherWebsites'].iteritems()])
        set_attr('covered_areas', 'coveredAreas')
        obj.tech_email = isp.tech_email
        return cls(obj=obj)
class ParamForm(FlaskForm):
    # parameters_list = ["iterations",
    #                    "num_tcls"
    #                    "tcl_power",
    #                    "tcl_price",
    #                    "num_loads",
    #                    "base_load",
    #                    "normal_price",
    #                    "temperatures",
    #                    "price_tiers",
    #                    "day0",
    #                    "dayn",
    #                    "power_cost",
    #                    "down_reg",
    #                    "up_reg",
    #                    "imp_fees",
    #                    "exp_fees",
    #                    "battery_capacity",
    #                    "max_discharge",
    #                    "max_charge"]
    iterations = IntegerField("Number of timesteps",validators=[Optional()])
    num_tcls = IntegerField("Number of TCLs",validators=[Optional()])
    tcl_power = FloatField("TCL average power kW",validators=[Optional()])
    tcl_price = FloatField("TCLs price",validators=[Optional()])
    num_loads = IntegerField("Number of loads",validators=[Optional()])
    # base_load = FloatField("Typical load",validators=[Optional()])
    normal_price = FloatField("Normal retail price",validators=[Optional()])
    # temperatures = FloatField("Temperatures",validators=[Optional()])
    day0 = IntegerField("Day 0",validators=[Optional()])
    # dayn = IntegerField("Day N",validators=[Optional()])
    power_cost = FloatField("power cost per kWh",validators=[Optional()])
    # down_reg = FloatField("Down regulation prices",validators=[Optional()])
    # up_reg = FloatField("Up regulation prices",validators=[Optional()])
    imp_fees = FloatField("Power Transmission fees (import) ",validators=[Optional()])
    exp_fees = FloatField("Power Transmission fees (export) ",validators=[Optional()])
    battery_capacity = FloatField("Battery Capacity kWh",validators=[Optional()])
    max_discharge = FloatField("Discharge limit per hour",validators=[Optional()])
    max_charge = FloatField("Charge limit per hour",validators=[Optional()])
    submit = SubmitField('Submit')
Пример #29
0
class CreateTimelineForm(BaseForm):
    """Form to handle ad-hoc timeline creation."""
    name = StringField('Timeline name', validators=[Optional()])
    sketch_id = IntegerField('Sketch ID', validators=[Optional()])
Пример #30
0
class SearchForm(Form):
    q = StringField('Search terms', [Optional(), Length(1, 256)])