mirror of
https://github.com/wassname/wtforms-parsleyjs.git
synced 2026-09-09 11:41:49 +08:00
Merge pull request #3 from SmileyJames/master
Increased Field and Validator support.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# WTForms-ParsleyJS
|
||||
# WTForms-ParsleyJS 2.0
|
||||
|
||||
## What is this?
|
||||
|
||||
@@ -16,32 +16,13 @@ This library will generate the necesssary HTML attributes from your WTForms vali
|
||||
|
||||
## Installation
|
||||
|
||||
You can install from [pypi](https://pypi.python.org/pypi/WTForms-ParsleyJS) using
|
||||
You can install from [pypi](https://pypi.python.org/pypi/WTForms-ParsleyJS) using
|
||||
|
||||
`pip install wtforms-parsleyjs`
|
||||
|
||||
## What is supported?
|
||||
|
||||
The following WTForms validators are supported:
|
||||
|
||||
* E-Mail Address
|
||||
* Matching values
|
||||
* IP4 Address
|
||||
* Length of string
|
||||
* Required field
|
||||
* Regexp (see limitations)
|
||||
* URL
|
||||
* `AnyOf`
|
||||
|
||||
The `NoneOf` validator is not supported because this functionality is not supported by ParsleyJS.
|
||||
|
||||
The following WTForms widgets are supported:
|
||||
|
||||
* TextInput
|
||||
* Select
|
||||
* CheckboxInput
|
||||
|
||||
Radio Buttons are not supported.
|
||||
All validators documented by WTForms are supported, all documented fields are also supported, with the exception of SubmitField. The reason SubmitField is not included is because I see no use case to validate Submit client side.
|
||||
|
||||
## How to use it?
|
||||
|
||||
@@ -67,9 +48,9 @@ WTForms-ParsleyJS has been developed and run solely on Python 2.7 - but it may w
|
||||
|
||||
## Dependencies
|
||||
|
||||
Of course ParsleyJS and WTForms are required. ParsleyJS in turn requires jQuery.
|
||||
Of course ParsleyJS and WTForms are required. ParsleyJS in turn requires jQuery.
|
||||
|
||||
The `AnyOf` validator requires parsleys extra validators which are distributed in a seperate file.
|
||||
If you wish to use AnyOf validator, NoneOf validator, DateField or DateTimeField then you need to include their matching ParsleyJS plugins, found in the scripts folder.
|
||||
|
||||
The sample uses the [Flask web framework](http://flask.pocoo.org/docs/) and [Twitter Bootstrap](http://twitter.github.io/bootstrap/). Because the sample should run out of the box on Heroku, ParsleyJS is included as a git submodule.
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('anyof', function (value, array) {
|
||||
return array.indexOf(value) >= 0;
|
||||
}, 32).addMessage('en', 'anyof', 'The value you have given is not a listed option.')
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('datefield', function (str, format) {
|
||||
/**
|
||||
* Modified version of micro-strptime.js.
|
||||
* https://github.com/cho45/micro-strptime.js
|
||||
*/
|
||||
if (!format) throw Error("Missing format");
|
||||
fds = {
|
||||
'%': '%',
|
||||
'A': '[a-z]+',
|
||||
'B': '[a-z]+',
|
||||
'Y': '[0-9]{4}',
|
||||
'm': '[0-9]{1,2}',
|
||||
'd': '[0-9]{1,2}',
|
||||
'H': '[0-9]{1,2}',
|
||||
'M': '[0-9]{1,2}',
|
||||
'S': '[0-9]{1,2}',
|
||||
's': '[0-9]+',
|
||||
'Z': 'UTC|Z|[+-][0-9][0-9]:?[0-9][0-9]',
|
||||
'I': '[0-9]{1,2}',
|
||||
'p': 'AM|PM'
|
||||
};
|
||||
// Create a regular expression from the format string, that matches a string of that format.
|
||||
var re = new RegExp(format.replace(/%(?:([a-zA-Z%])|('[^']+')|("[^"]+"))/g, function (_, a, b, c) {
|
||||
var fd = a || b || c;
|
||||
var d = fds[fd];
|
||||
if (!d) throw Error("Unknown format descripter: " + fd);
|
||||
return '(' + d + ')';
|
||||
}), 'i');
|
||||
return re.test(str);
|
||||
}, 32).addMessage('en', 'datefield', 'The input needs to be in the correct date format.')
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('noneof', function (value, array) {
|
||||
return array.indexOf(value) === -1;
|
||||
}, 32).addMessage('en', 'noneof', 'You have entered a value which is not allowed.')
|
||||
});
|
||||
+76
-28
@@ -2,25 +2,28 @@ __author__ = 'Johannes Gehrs (jgehrs@gmail.com)'
|
||||
|
||||
import re
|
||||
import copy
|
||||
import json
|
||||
|
||||
from wtforms.validators import Length, NumberRange, Email, EqualTo, IPAddress, \
|
||||
Regexp, URL, AnyOf, Optional, InputRequired
|
||||
Regexp, URL, AnyOf, Optional, InputRequired, MacAddress, UUID, NoneOf
|
||||
try:
|
||||
from wtforms.validators import DataRequired
|
||||
except ImportError:
|
||||
# wtforms < 2.x
|
||||
from wtforms.validators import Required as DataRequired
|
||||
|
||||
from wtforms import StringField
|
||||
from wtforms.widgets import TextInput as _TextInput, PasswordInput as _PasswordInput, \
|
||||
CheckboxInput as _CheckboxInput, Select as _Select, TextArea as _TextArea, \
|
||||
ListWidget as _ListWidget, HiddenInput as _HiddenInput, RadioInput as _RadioInput, \
|
||||
Input
|
||||
FileInput as _FileInput, Input
|
||||
|
||||
from wtforms.fields import StringField as _StringField, BooleanField as _BooleanField, \
|
||||
DecimalField as _DecimalField, IntegerField as _IntegerField, \
|
||||
FloatField as _FloatField, PasswordField as _PasswordField, \
|
||||
SelectField as _SelectField, TextAreaField as _TextAreaField, \
|
||||
RadioField as _RadioField
|
||||
RadioField as _RadioField, DateField as _DateField, \
|
||||
DateTimeField as _DateTimeField, FileField as _FileField, \
|
||||
SelectMultipleField as _SelectMultipleField
|
||||
|
||||
|
||||
def parsley_kwargs(field, kwargs):
|
||||
@@ -39,6 +42,16 @@ def parsley_kwargs(field, kwargs):
|
||||
one. Do check if the behaviour suits your needs.
|
||||
"""
|
||||
new_kwargs = copy.deepcopy(kwargs)
|
||||
|
||||
if isinstance(field, DateField) or isinstance(field, DateTimeField):
|
||||
_date_kwargs(new_kwargs, field)
|
||||
if isinstance(field, IntegerField):
|
||||
_integer_kwargs(new_kwargs)
|
||||
if isinstance(field, DecimalField) or isinstance(field, FloatField):
|
||||
_number_kwargs(new_kwargs)
|
||||
if not 'data_trigger' in new_kwargs:
|
||||
_trigger_kwargs(new_kwargs)
|
||||
|
||||
for vali in field.validators:
|
||||
if isinstance(vali, Email):
|
||||
_email_kwargs(new_kwargs)
|
||||
@@ -59,11 +72,15 @@ def parsley_kwargs(field, kwargs):
|
||||
_url_kwargs(new_kwargs)
|
||||
if isinstance(vali, AnyOf):
|
||||
_anyof_kwargs(new_kwargs, vali)
|
||||
if isinstance(vali, MacAddress):
|
||||
_mac_address_kwargs(new_kwargs)
|
||||
if isinstance(vali, UUID):
|
||||
_uuid_kwargs(new_kwargs)
|
||||
if isinstance(vali, NoneOf):
|
||||
_none_of_kwargs(new_kwargs, vali)
|
||||
if isinstance(vali, Optional):
|
||||
pass
|
||||
|
||||
if not 'data_trigger' in new_kwargs:
|
||||
_trigger_kwargs(new_kwargs)
|
||||
if not 'parsley-error-message' in new_kwargs \
|
||||
and not isinstance(vali, Optional) \
|
||||
and vali.message is not None:
|
||||
@@ -81,7 +98,7 @@ def _equal_to_kwargs(kwargs, vali):
|
||||
|
||||
def _ip_address_kwargs(kwargs):
|
||||
# Regexp from http://stackoverflow.com/a/4460645
|
||||
kwargs[u'data-parsley-regexp'] =\
|
||||
kwargs[u'data-parsley-pattern'] =\
|
||||
r'^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
|
||||
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
|
||||
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
|
||||
@@ -115,38 +132,40 @@ def _regexp_kwargs(kwargs, vali):
|
||||
regex_string = vali.regex.pattern
|
||||
else:
|
||||
regex_string = vali.regex
|
||||
kwargs[u'data-parsley-regexp'] = regex_string
|
||||
kwargs[u'data-parsley-pattern'] = regex_string
|
||||
|
||||
def _url_kwargs(kwargs):
|
||||
kwargs[u'data-parsley-type'] = u'url'
|
||||
|
||||
def _string_seq_delimiter(vali, kwargs):
|
||||
# We normally use a comma as the delimiter - looks clean and it's parsley's default.
|
||||
# If the strings for which we check contain a comma, we cannot use it as a delimiter.
|
||||
default_delimiter = u','
|
||||
fallback_delimiter = u';;;'
|
||||
delimiter = default_delimiter
|
||||
for value in vali.values:
|
||||
if value.find(',') != -1:
|
||||
delimiter = fallback_delimiter
|
||||
break
|
||||
if delimiter != default_delimiter:
|
||||
kwargs[u'data-parsley-inlist-delimiter'] = delimiter
|
||||
return delimiter
|
||||
|
||||
|
||||
def _anyof_kwargs(kwargs, vali):
|
||||
delimiter = _string_seq_delimiter(vali, kwargs)
|
||||
kwargs[u'data-parsley-inlist'] = delimiter.join(vali.values)
|
||||
# The inlist validator is no longer available in Parsley 2.x, so a custom anyof validator is used.
|
||||
kwargs[u'data-parsley-anyof'] = json.dumps(vali.values)
|
||||
|
||||
def _mac_address_kwargs(kwargs):
|
||||
kwargs[u'data-parsley-pattern'] = '^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'
|
||||
|
||||
def _uuid_kwargs(kwargs):
|
||||
kwargs[u'data-parsley-pattern'] = '^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$'
|
||||
|
||||
def _none_of_kwargs(kwargs, vali):
|
||||
#data-parsley-noneof is a custom validator, it can be found in scripts/parsley-noneof.js
|
||||
kwargs[u'data-parsley-noneof'] = json.dumps(vali.values)
|
||||
|
||||
def _trigger_kwargs(kwargs, trigger=u'change'):
|
||||
kwargs[u'data-parsley-trigger'] = trigger
|
||||
|
||||
|
||||
def _message_kwargs(kwargs, message):
|
||||
kwargs[u'data-parsley-error-message'] = message
|
||||
|
||||
def _date_kwargs(kwargs, field):
|
||||
kwargs[u'data-parsley-datefield'] = field.format
|
||||
|
||||
def _integer_kwargs(kwargs):
|
||||
kwargs[u'data-parsley-type'] = "integer"
|
||||
|
||||
def _number_kwargs(kwargs):
|
||||
kwargs[u'data-parsley-type'] = "number"
|
||||
|
||||
|
||||
class ParsleyInputMixin(Input):
|
||||
def __call__(self, field, **kwargs):
|
||||
@@ -166,8 +185,10 @@ class HiddenInput(_HiddenInput, ParsleyInputMixin):
|
||||
pass
|
||||
|
||||
|
||||
class TextArea(_TextArea, ParsleyInputMixin):
|
||||
pass
|
||||
class TextArea(_TextArea):
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs = parsley_kwargs(field, kwargs)
|
||||
return super(TextArea, self).__call__(field, **kwargs)
|
||||
|
||||
|
||||
class CheckboxInput(_CheckboxInput, ParsleyInputMixin):
|
||||
@@ -193,6 +214,12 @@ class ListWidget(_ListWidget):
|
||||
return super(ListWidget, self).__call__(field, **kwargs)
|
||||
|
||||
|
||||
class FileInput(_FileInput):
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs = parsley_kwargs(field, kwargs)
|
||||
return super(FileInput, self).__call__(field, **kwargs)
|
||||
|
||||
|
||||
class StringField(_StringField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StringField, self).__init__(widget=TextInput(), *args, **kwargs)
|
||||
@@ -243,3 +270,24 @@ class TextAreaField(_TextAreaField):
|
||||
class SelectField(_SelectField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SelectField, self).__init__(widget=Select(), *args, **kwargs)
|
||||
|
||||
|
||||
class DateTimeField(_DateTimeField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DateTimeField, self).__init__(widget=TextInput(), *args, **kwargs)
|
||||
|
||||
|
||||
class DateField(_DateField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DateField, self).__init__(widget=TextInput(), *args, **kwargs)
|
||||
|
||||
|
||||
class FileField(_FileField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FileField, self).__init__(widget=FileInput(), *args, **kwargs)
|
||||
|
||||
|
||||
class SelectMultipleField(_SelectMultipleField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SelectMultipleField, self).__init__(widget=Select(multiple=True), *args, **kwargs)
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ __author__ = 'Johannes Gehrs (jgehrs@gmail.com)'
|
||||
|
||||
from flask import Flask, render_template, request
|
||||
from wtforms import Form, validators
|
||||
from wtformsparsleyjs import IntegerField, BooleanField, SelectField, StringField
|
||||
import wtformsparsleyjs
|
||||
import datetime
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -15,46 +16,283 @@ def parsley_testform():
|
||||
|
||||
|
||||
class ParsleyTestForm(Form):
|
||||
email = StringField('E-Mail Address', [
|
||||
validators.Email('Sorrry, not a valid email address.')
|
||||
], default='test@example.com')
|
||||
first_value = StringField('Some Value', default='Some value')
|
||||
second_value = StringField('Should be identical', [
|
||||
validators.EqualTo(message='Sorry, values do not match.',
|
||||
fieldname='first_value')
|
||||
], default='Some value')
|
||||
ip_address = StringField('IP4 Address', [
|
||||
validators.IPAddress(message='Sorry, not a valid IP4 Address.')
|
||||
], default='127.0.0.1')
|
||||
string_length = StringField('Length of String (5 to 10)', [
|
||||
validators.Length(message='Length should be between 5 and 10 characters.',
|
||||
min=5, max=10)
|
||||
], default='Hello!')
|
||||
number_range = IntegerField('Number Range (5 to 10)', [
|
||||
validators.NumberRange(message='Range should be between 5 and 10.',
|
||||
min=5, max=10)
|
||||
], default=7)
|
||||
email = wtformsparsleyjs.StringField(
|
||||
label = 'E-Mail Address',
|
||||
validators = [
|
||||
validators.Email(
|
||||
message = 'Sorrry, not a valid email address.'
|
||||
)
|
||||
],
|
||||
default='test@example.com'
|
||||
)
|
||||
|
||||
required_text = StringField('Required Field', [
|
||||
validators.DataRequired(message='Sorry, this is a required field.')
|
||||
], default='Mandatory text')
|
||||
required_select = SelectField('Required Select', [
|
||||
validators.DataRequired(
|
||||
message='Sorry, you have to make a choice.')
|
||||
], choices=[('', 'Please select an option'), ('cpp', 'C++'), ('py', 'Python'),
|
||||
('text', 'Plain Text')
|
||||
], default='py')
|
||||
required_checkbox = BooleanField('Required Checkbox', [
|
||||
validators.DataRequired(message='Sorry, you need to accept this.')
|
||||
], default=True)
|
||||
regexp = StringField('Regex-Matched Hex Color-Code', [
|
||||
validators.Regexp(message='Not a proper color code, sorry.',
|
||||
regex=r'^#[A-Fa-f0-9]{6}$')
|
||||
], default='#7D384F')
|
||||
url = StringField('URL Field', [
|
||||
validators.URL(message='Sorry, this is not a valid URL,')
|
||||
], default='http://example.com/parsley')
|
||||
anyof = StringField('Car, Bike or Plane?', [
|
||||
validators.AnyOf(message='Sorry, you can only choose from car, bike and plane',
|
||||
values=['car', 'bike', 'plane'])
|
||||
], default='car')
|
||||
ip_address = wtformsparsleyjs.StringField(
|
||||
label = 'IP4 Address',
|
||||
validators = [
|
||||
validators.IPAddress(
|
||||
message = 'Sorry, not a valid IP4 Address.'
|
||||
)
|
||||
],
|
||||
default='127.0.0.1'
|
||||
)
|
||||
|
||||
uuid = wtformsparsleyjs.StringField(
|
||||
label = 'UUID',
|
||||
validators = [
|
||||
validators.UUID(
|
||||
message = 'Sorry, not a valid UUID.'
|
||||
)
|
||||
],
|
||||
default='863b5570-ee85-4099-ba1d-33018282cd00'
|
||||
)
|
||||
|
||||
mac_address = wtformsparsleyjs.StringField(
|
||||
label = 'Mac Address',
|
||||
validators = [
|
||||
validators.MacAddress(
|
||||
message = 'Sorry, not a valid mac address.'
|
||||
)
|
||||
],
|
||||
default = '10:B0:46:8C:80:48'
|
||||
)
|
||||
|
||||
string_length = wtformsparsleyjs.StringField(
|
||||
label = 'Length of String (5 to 10)',
|
||||
validators = [
|
||||
validators.Length(
|
||||
message = 'Length should be between 5 and 10 characters.',
|
||||
min = 5,
|
||||
max = 10
|
||||
)
|
||||
],
|
||||
default = 'Hello!'
|
||||
)
|
||||
|
||||
number_range = wtformsparsleyjs.IntegerField(
|
||||
label = 'Number Range (5 to 10)',
|
||||
validators = [
|
||||
validators.NumberRange(
|
||||
message = 'Range should be between 5 and 10.',
|
||||
min = 5,
|
||||
max = 10
|
||||
)
|
||||
],
|
||||
default = 7
|
||||
)
|
||||
|
||||
required_text = wtformsparsleyjs.StringField(
|
||||
label = 'Required Field',
|
||||
validators = [
|
||||
validators.DataRequired(
|
||||
message = 'Sorry, this is a required field.'
|
||||
)
|
||||
],
|
||||
default = 'Mandatory text'
|
||||
)
|
||||
|
||||
required_select = wtformsparsleyjs.SelectField(
|
||||
label = 'Required Select',
|
||||
validators = [
|
||||
validators.DataRequired(
|
||||
message = 'Sorry, you have to make a choice.'
|
||||
)
|
||||
],
|
||||
choices=[
|
||||
('', 'Please select an option'),
|
||||
('cpp', 'C++'),
|
||||
('py', 'Python'),
|
||||
('text', 'Plain Text')
|
||||
],
|
||||
default = 'py'
|
||||
)
|
||||
|
||||
required_checkbox = wtformsparsleyjs.BooleanField(
|
||||
label = 'Required Checkbox',
|
||||
validators = [
|
||||
validators.DataRequired(
|
||||
message = 'Sorry, you need to accept this.'
|
||||
)
|
||||
],
|
||||
default = True
|
||||
)
|
||||
|
||||
regexp = wtformsparsleyjs.StringField(
|
||||
label = 'Regex-Matched Hex Color-Code',
|
||||
validators = [
|
||||
validators.Regexp(
|
||||
message = 'Not a proper color code, sorry.',
|
||||
regex = r'^#[A-Fa-f0-9]{6}$'
|
||||
)
|
||||
],
|
||||
default = '#7D384F'
|
||||
)
|
||||
|
||||
url = wtformsparsleyjs.StringField(
|
||||
label = 'URL Field',
|
||||
validators = [
|
||||
validators.URL(
|
||||
message = 'Sorry, this is not a valid URL,'
|
||||
)
|
||||
],
|
||||
default = 'http://example.com/parsley'
|
||||
)
|
||||
|
||||
anyof = wtformsparsleyjs.StringField(
|
||||
'Car, Bike or Plane?',
|
||||
validators = [
|
||||
validators.AnyOf(
|
||||
message = 'Sorry, you can only choose from car, bike and plane',
|
||||
values = ['car', 'bike', 'plane']
|
||||
)
|
||||
],
|
||||
default = 'car'
|
||||
)
|
||||
|
||||
date_of_birth = wtformsparsleyjs.DateField(
|
||||
label = "Date of birth in the format DD-MM-YYYY",
|
||||
format = "%d-%m-%Y",
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
],
|
||||
default = datetime.datetime.today().date()
|
||||
)
|
||||
|
||||
date_time = wtformsparsleyjs.DateTimeField(
|
||||
label = "Date and time in the format DD/MM/YYYY HH:MM",
|
||||
format = "%d/%m/%Y %H:%M",
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
],
|
||||
default = datetime.datetime.today()
|
||||
)
|
||||
|
||||
length = wtformsparsleyjs.DecimalField(
|
||||
label = "Exact length, as a decimal",
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
],
|
||||
default = 4.20
|
||||
)
|
||||
|
||||
txt_file = wtformsparsleyjs.FileField(
|
||||
label = "Optional file field, of .txt format",
|
||||
validators = [
|
||||
validators.Regexp(
|
||||
r"^.+\.txt$",
|
||||
message="Must be a *.txt file"
|
||||
),
|
||||
validators.Optional()
|
||||
]
|
||||
)
|
||||
|
||||
float_field = wtformsparsleyjs.FloatField(
|
||||
label = "A float value",
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
],
|
||||
default = 4.20
|
||||
)
|
||||
|
||||
best_thing_ever = wtformsparsleyjs.RadioField(
|
||||
label = "Is this the best thing ever?",
|
||||
choices = [
|
||||
("y", "Yes"),
|
||||
("n", "No")
|
||||
],
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "We need and answer please."
|
||||
)
|
||||
],
|
||||
default = "y"
|
||||
)
|
||||
|
||||
colour = wtformsparsleyjs.SelectField(
|
||||
label = "Select your favourite colour.",
|
||||
choices = [
|
||||
("red", "Red"),
|
||||
("blue", "Blue"),
|
||||
("green", "Green")
|
||||
],
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
hobbies = wtformsparsleyjs.SelectMultipleField(
|
||||
label = "Select your hobbies: ",
|
||||
choices=[
|
||||
("cooking", "Cooking"),
|
||||
("coding", "Coding"),
|
||||
("reading", "Reading"),
|
||||
("fishing", "Fishing"),
|
||||
("sewing", "Sewing")
|
||||
],
|
||||
validators = [
|
||||
validators.Optional()
|
||||
]
|
||||
)
|
||||
|
||||
name = wtformsparsleyjs.StringField(
|
||||
label = "Whom would you have me welease?",
|
||||
validators = [
|
||||
validators.NoneOf(
|
||||
["Roger", "Roderick", "Woger", "Woderick"],
|
||||
message = "Ah. We have no Woger and no Woderick"
|
||||
)
|
||||
],
|
||||
default = "Brian"
|
||||
)
|
||||
|
||||
hidden = wtformsparsleyjs.HiddenField(
|
||||
label = "Hidden value",
|
||||
validators = [
|
||||
validators.NumberRange(
|
||||
min = 5,
|
||||
message = "Must be greater than 5"
|
||||
)
|
||||
],
|
||||
default = 6
|
||||
)
|
||||
|
||||
# No default values for passwords, becuase the aren't rendered as a safety
|
||||
# feature.
|
||||
secret = wtformsparsleyjs.PasswordField(
|
||||
label = "Enter your secret:",
|
||||
validators = [
|
||||
validators.InputRequired(
|
||||
message = "Sorry this input is required."
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
same_secret = wtformsparsleyjs.PasswordField(
|
||||
label = "Enter your secret again: ",
|
||||
validators = [
|
||||
validators.EqualTo(
|
||||
fieldname = "secret",
|
||||
message = "Secrets do not match."
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
life_story = wtformsparsleyjs.TextAreaField(
|
||||
label = "Tell us your life story...",
|
||||
validators = [
|
||||
validators.Length(
|
||||
min = 50,
|
||||
message = "C'mon that's not long enough to be a life story"
|
||||
)
|
||||
],
|
||||
default = "This is my life story, it has to be at least 50 characters."
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('anyof', function (value, array) {
|
||||
return array.indexOf(value) >= 0;
|
||||
}, 32).addMessage('en', 'anyof', 'The value you have given is not a listed option.')
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('datefield', function (str, format) {
|
||||
/**
|
||||
* Modified version of micro-strptime.js.
|
||||
* https://github.com/cho45/micro-strptime.js
|
||||
*/
|
||||
if (!format) throw Error("Missing format");
|
||||
fds = {
|
||||
'%': '%',
|
||||
'A': '[a-z]+',
|
||||
'B': '[a-z]+',
|
||||
'Y': '[0-9]{4}',
|
||||
'm': '[0-9]{1,2}',
|
||||
'd': '[0-9]{1,2}',
|
||||
'H': '[0-9]{1,2}',
|
||||
'M': '[0-9]{1,2}',
|
||||
'S': '[0-9]{1,2}',
|
||||
's': '[0-9]+',
|
||||
'Z': 'UTC|Z|[+-][0-9][0-9]:?[0-9][0-9]',
|
||||
'I': '[0-9]{1,2}',
|
||||
'p': 'AM|PM'
|
||||
};
|
||||
// Create a regular expression from the format string, that matches a string of that format.
|
||||
var re = new RegExp(format.replace(/%(?:([a-zA-Z%])|('[^']+')|("[^"]+"))/g, function (_, a, b, c) {
|
||||
var fd = a || b || c;
|
||||
var d = fds[fd];
|
||||
if (!d) throw Error("Unknown format descripter: " + fd);
|
||||
return '(' + d + ')';
|
||||
}), 'i');
|
||||
return re.test(str);
|
||||
}, 32).addMessage('en', 'datefield', 'The input needs to be in the correct date format.')
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
$(document).ready(function() {
|
||||
window.ParsleyValidator.addValidator('noneof', function (value, array) {
|
||||
return array.indexOf(value) === -1;
|
||||
}, 32).addMessage('en', 'noneof', 'You have entered a value which is not allowed.')
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,8 +45,10 @@
|
||||
|
||||
{% block scripts %}
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsleyjs/parsley.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsleyjs/parsley.extend.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsley.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsley-noneof.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsley-anyof.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='scripts/parsley-datefield.js') }}"></script>
|
||||
<script>$('form').parsley({ successClass: 'success', errorClass: 'error',
|
||||
errors: {
|
||||
classHandler: function (element) {
|
||||
|
||||
@@ -5,19 +5,10 @@
|
||||
{% from "_formhelpers.html" import render_field, render_checkbox %}
|
||||
<form method=post action="{{ url_for('parsley_testform') }}">
|
||||
<fieldset>
|
||||
{{ render_field(form.email) }}
|
||||
{{ render_field(form.first_value) }}
|
||||
{{ render_field(form.second_value) }}
|
||||
{{ render_field(form.ip_address) }}
|
||||
{{ render_field(form.string_length) }}
|
||||
{{ render_field(form.number_range) }}
|
||||
{{ render_field(form.required_text) }}
|
||||
{{ render_field(form.required_select) }}
|
||||
{{ render_field(form.required_checkbox) }}
|
||||
{{ render_field(form.regexp) }}
|
||||
{{ render_field(form.url) }}
|
||||
{{ render_field(form.anyof) }}
|
||||
{% for field in form %}
|
||||
{{ render_field(field) }}
|
||||
{% endfor %}
|
||||
<p><input type=submit value=Submit>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
{% endblock content %}
|
||||
|
||||
Reference in New Issue
Block a user