I have numerous regular expressions, such as:
quantity_validation = re.compile("""^-?[0-9]+$""", re.I)
I use these regex in functions like:
def validate_quantity(self, value):
if value != self.context.quantity:
# while not self.quantity_validation.match(value):
# return 0, "Value is not a number"
if not self.quantity_validation.match(value):
return 0, "Value is not a number"
return 1, ""
and the validation method:
#view_config(name="validate", renderer='json')
def validate(self, full={}):
def do_validation(field, value):
message = ""
valid = 1
if getattr(self, 'validate_%s' % field, False):
valid, message = getattr(self, 'validate_%s' % field)(value)
out = dict(message=message, valid=valid, value=value)
return out
if not full:
field = self.request.params.get('field')
if not field:
return "INVALID"
return do_validation(field, self.request.params.get('value'))
else:
return dict(((field, do_validation(field, value)) for field, value in full.items()))
On the HTML form I have a modal with a quantity field on which I do ajax validation(I use jqBootstrapValidation to validate my forms)
The regex validation works fine until I type a + then the validation stop working until I refresh the page.
Why does the validation stop working?
Is it perhaps a bug in jqBootstrapValidation?
or is it a bug in the re module?
You are not encoding your URLs/inputs correctly. The '+' gets parsed into a ' ' when you pass it via the parameter string. Try '%2B' instead which should be decoded into a '+' through the form library.
Related
Django: 3.0.5
Python: 3.7.3
I am rather new to Django's framework and I have been trying to create a custom user model so that the default username is an email. However, I cannot seem to create a superuser. I keep getting this error after calling py manage.py createsuperuser:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
utility.execute()
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\core\management\__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\core\management\base.py", line 320, in run_from_argv
parser = self.create_parser(argv[0], argv[1])
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\core\management\base.py", line 294, in create_parser
self.add_arguments(parser)
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\contrib\auth\management\commands\createsuperuser.py", line 55, in add_arguments
field = self.UserModel._meta.get_field(field_name)
File "C:\Users\User\Dev\tryDjango\lib\site-packages\django\db\models\options.py", line 583, in get_field
raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: User has no field named ''
Below is the codes for my custom user model, I have also placed AUTH_USER_MODEL = 'accounts.User' in my settings.py.
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError("Users must have an Email address")
if not password:
raise ValueError("Users must have a Password")
user = self.model(
email=self.normalize_email(email)
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, password=None):
user = self.create_user(
email,
password=password
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, password=None):
user = self.create_user(
email,
password=password
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
# full_name = models.CharField(max_length=255, blank=False)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['']
objects = UserManager()
def get_full_name(self):
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
Appreciate any help! Oh and can anyone explain to me why do I need to write these codes under the User class? I don't see why I'd need it and I also don't see why is there a need for a Getter #property. Sorry if these are stupid questions.
def get_full_name(self):
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
EDIT: Serializer.py
from __future__ import absolute_import, division, unicode_literals
from pip._vendor.six import text_type
import re
from codecs import register_error, xmlcharrefreplace_errors
from .constants import voidElements, booleanAttributes, spaceCharacters
from .constants import rcdataElements, entities, xmlEntities
from . import treewalkers, _utils
from xml.sax.saxutils import escape
_quoteAttributeSpecChars = "".join(spaceCharacters) + "\"'=<>`"
_quoteAttributeSpec = re.compile("[" + _quoteAttributeSpecChars + "]")
_quoteAttributeLegacy = re.compile("[" + _quoteAttributeSpecChars +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n"
"\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15"
"\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x2f\x60\xa0\u1680\u180e\u180f\u2000"
"\u2001\u2002\u2003\u2004\u2005\u2006\u2007"
"\u2008\u2009\u200a\u2028\u2029\u202f\u205f"
"\u3000]")
_encode_entity_map = {}
_is_ucs4 = len("\U0010FFFF") == 1
for k, v in list(entities.items()):
# skip multi-character entities
if ((_is_ucs4 and len(v) > 1) or
(not _is_ucs4 and len(v) > 2)):
continue
if v != "&":
if len(v) == 2:
v = _utils.surrogatePairToCodepoint(v)
else:
v = ord(v)
if v not in _encode_entity_map or k.islower():
# prefer < over < and similarly for &, >, etc.
_encode_entity_map[v] = k
def htmlentityreplace_errors(exc):
if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)):
res = []
codepoints = []
skip = False
for i, c in enumerate(exc.object[exc.start:exc.end]):
if skip:
skip = False
continue
index = i + exc.start
if _utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]):
codepoint = _utils.surrogatePairToCodepoint(exc.object[index:index + 2])
skip = True
else:
codepoint = ord(c)
codepoints.append(codepoint)
for cp in codepoints:
e = _encode_entity_map.get(cp)
if e:
res.append("&")
res.append(e)
if not e.endswith(";"):
res.append(";")
else:
res.append("&#x%s;" % (hex(cp)[2:]))
return ("".join(res), exc.end)
else:
return xmlcharrefreplace_errors(exc)
register_error("htmlentityreplace", htmlentityreplace_errors)
def serialize(input, tree="etree", encoding=None, **serializer_opts):
"""Serializes the input token stream using the specified treewalker
:arg input: the token stream to serialize
:arg tree: the treewalker to use
:arg encoding: the encoding to use
:arg serializer_opts: any options to pass to the
:py:class:`html5lib.serializer.HTMLSerializer` that gets created
:returns: the tree serialized as a string
Example:
>>> from html5lib.html5parser import parse
>>> from html5lib.serializer import serialize
>>> token_stream = parse('<html><body><p>Hi!</p></body></html>')
>>> serialize(token_stream, omit_optional_tags=False)
'<html><head></head><body><p>Hi!</p></body></html>'
"""
# XXX: Should we cache this?
walker = treewalkers.getTreeWalker(tree)
s = HTMLSerializer(**serializer_opts)
return s.render(walker(input), encoding)
class HTMLSerializer(object):
# attribute quoting options
quote_attr_values = "legacy" # be secure by default
quote_char = '"'
use_best_quote_char = True
# tag syntax options
omit_optional_tags = True
minimize_boolean_attributes = True
use_trailing_solidus = False
space_before_trailing_solidus = True
# escaping options
escape_lt_in_attrs = False
escape_rcdata = False
resolve_entities = True
# miscellaneous options
alphabetical_attributes = False
inject_meta_charset = True
strip_whitespace = False
sanitize = False
options = ("quote_attr_values", "quote_char", "use_best_quote_char",
"omit_optional_tags", "minimize_boolean_attributes",
"use_trailing_solidus", "space_before_trailing_solidus",
"escape_lt_in_attrs", "escape_rcdata", "resolve_entities",
"alphabetical_attributes", "inject_meta_charset",
"strip_whitespace", "sanitize")
def __init__(self, **kwargs):
"""Initialize HTMLSerializer
:arg inject_meta_charset: Whether or not to inject the meta charset.
Defaults to ``True``.
:arg quote_attr_values: Whether to quote attribute values that don't
require quoting per legacy browser behavior (``"legacy"``), when
required by the standard (``"spec"``), or always (``"always"``).
Defaults to ``"legacy"``.
:arg quote_char: Use given quote character for attribute quoting.
Defaults to ``"`` which will use double quotes unless attribute
value contains a double quote, in which case single quotes are
used.
:arg escape_lt_in_attrs: Whether or not to escape ``<`` in attribute
values.
Defaults to ``False``.
:arg escape_rcdata: Whether to escape characters that need to be
escaped within normal elements within rcdata elements such as
style.
Defaults to ``False``.
:arg resolve_entities: Whether to resolve named character entities that
appear in the source tree. The XML predefined entities < >
& " ' are unaffected by this setting.
Defaults to ``True``.
:arg strip_whitespace: Whether to remove semantically meaningless
whitespace. (This compresses all whitespace to a single space
except within ``pre``.)
Defaults to ``False``.
:arg minimize_boolean_attributes: Shortens boolean attributes to give
just the attribute value, for example::
<input disabled="disabled">
becomes::
<input disabled>
Defaults to ``True``.
:arg use_trailing_solidus: Includes a close-tag slash at the end of the
start tag of void elements (empty elements whose end tag is
forbidden). E.g. ``<hr/>``.
Defaults to ``False``.
:arg space_before_trailing_solidus: Places a space immediately before
the closing slash in a tag using a trailing solidus. E.g.
``<hr />``. Requires ``use_trailing_solidus=True``.
Defaults to ``True``.
:arg sanitize: Strip all unsafe or unknown constructs from output.
See :py:class:`html5lib.filters.sanitizer.Filter`.
Defaults to ``False``.
:arg omit_optional_tags: Omit start/end tags that are optional.
Defaults to ``True``.
:arg alphabetical_attributes: Reorder attributes to be in alphabetical order.
Defaults to ``False``.
"""
unexpected_args = frozenset(kwargs) - frozenset(self.options)
if len(unexpected_args) > 0:
raise TypeError("__init__() got an unexpected keyword argument '%s'" % next(iter(unexpected_args)))
if 'quote_char' in kwargs:
self.use_best_quote_char = False
for attr in self.options:
setattr(self, attr, kwargs.get(attr, getattr(self, attr)))
self.errors = []
self.strict = False
def encode(self, string):
assert(isinstance(string, text_type))
if self.encoding:
return string.encode(self.encoding, "htmlentityreplace")
else:
return string
def encodeStrict(self, string):
assert(isinstance(string, text_type))
if self.encoding:
return string.encode(self.encoding, "strict")
else:
return string
def serialize(self, treewalker, encoding=None):
# pylint:disable=too-many-nested-blocks
self.encoding = encoding
in_cdata = False
self.errors = []
if encoding and self.inject_meta_charset:
from .filters.inject_meta_charset import Filter
treewalker = Filter(treewalker, encoding)
# Alphabetical attributes is here under the assumption that none of
# the later filters add or change order of attributes; it needs to be
# before the sanitizer so escaped elements come out correctly
if self.alphabetical_attributes:
from .filters.alphabeticalattributes import Filter
treewalker = Filter(treewalker)
# WhitespaceFilter should be used before OptionalTagFilter
# for maximum efficiently of this latter filter
if self.strip_whitespace:
from .filters.whitespace import Filter
treewalker = Filter(treewalker)
if self.sanitize:
from .filters.sanitizer import Filter
treewalker = Filter(treewalker)
if self.omit_optional_tags:
from .filters.optionaltags import Filter
treewalker = Filter(treewalker)
for token in treewalker:
type = token["type"]
if type == "Doctype":
doctype = "<!DOCTYPE %s" % token["name"]
if token["publicId"]:
doctype += ' PUBLIC "%s"' % token["publicId"]
elif token["systemId"]:
doctype += " SYSTEM"
if token["systemId"]:
if token["systemId"].find('"') >= 0:
if token["systemId"].find("'") >= 0:
self.serializeError("System identifer contains both single and double quote characters")
quote_char = "'"
else:
quote_char = '"'
doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char)
doctype += ">"
yield self.encodeStrict(doctype)
elif type in ("Characters", "SpaceCharacters"):
if type == "SpaceCharacters" or in_cdata:
if in_cdata and token["data"].find("</") >= 0:
self.serializeError("Unexpected </ in CDATA")
yield self.encode(token["data"])
else:
yield self.encode(escape(token["data"]))
elif type in ("StartTag", "EmptyTag"):
name = token["name"]
yield self.encodeStrict("<%s" % name)
if name in rcdataElements and not self.escape_rcdata:
in_cdata = True
elif in_cdata:
self.serializeError("Unexpected child element of a CDATA element")
for (_, attr_name), attr_value in token["data"].items():
# TODO: Add namespace support here
k = attr_name
v = attr_value
yield self.encodeStrict(' ')
yield self.encodeStrict(k)
if not self.minimize_boolean_attributes or \
(k not in booleanAttributes.get(name, tuple()) and
k not in booleanAttributes.get("", tuple())):
yield self.encodeStrict("=")
if self.quote_attr_values == "always" or len(v) == 0:
quote_attr = True
elif self.quote_attr_values == "spec":
quote_attr = _quoteAttributeSpec.search(v) is not None
elif self.quote_attr_values == "legacy":
quote_attr = _quoteAttributeLegacy.search(v) is not None
else:
raise ValueError("quote_attr_values must be one of: "
"'always', 'spec', or 'legacy'")
v = v.replace("&", "&")
if self.escape_lt_in_attrs:
v = v.replace("<", "<")
if quote_attr:
quote_char = self.quote_char
if self.use_best_quote_char:
if "'" in v and '"' not in v:
quote_char = '"'
elif '"' in v and "'" not in v:
quote_char = "'"
if quote_char == "'":
v = v.replace("'", "'")
else:
v = v.replace('"', """)
yield self.encodeStrict(quote_char)
yield self.encode(v)
yield self.encodeStrict(quote_char)
else:
yield self.encode(v)
if name in voidElements and self.use_trailing_solidus:
if self.space_before_trailing_solidus:
yield self.encodeStrict(" /")
else:
yield self.encodeStrict("/")
yield self.encode(">")
elif type == "EndTag":
name = token["name"]
if name in rcdataElements:
in_cdata = False
elif in_cdata:
self.serializeError("Unexpected child element of a CDATA element")
yield self.encodeStrict("</%s>" % name)
elif type == "Comment":
data = token["data"]
if data.find("--") >= 0:
self.serializeError("Comment contains --")
yield self.encodeStrict("<!--%s-->" % token["data"])
elif type == "Entity":
name = token["name"]
key = name + ";"
if key not in entities:
self.serializeError("Entity %s not recognized" % name)
if self.resolve_entities and key not in xmlEntities:
data = entities[key]
else:
data = "&%s;" % name
yield self.encodeStrict(data)
else:
self.serializeError(token["data"])
def render(self, treewalker, encoding=None):
"""Serializes the stream from the treewalker into a string
:arg treewalker: the treewalker to serialize
:arg encoding: the string encoding to use
:returns: the serialized tree
Example:
>>> from html5lib import parse, getTreeWalker
>>> from html5lib.serializer import HTMLSerializer
>>> token_stream = parse('<html><body>Hi!</body></html>')
>>> walker = getTreeWalker('etree')
>>> serializer = HTMLSerializer(omit_optional_tags=False)
>>> serializer.render(walker(token_stream))
'<html><head></head><body>Hi!</body></html>'
"""
if encoding:
return b"".join(list(self.serialize(treewalker, encoding)))
else:
return "".join(list(self.serialize(treewalker)))
def serializeError(self, data="XXX ERROR MESSAGE NEEDED"):
# XXX The idea is to make data mandatory.
self.errors.append(data)
if self.strict:
raise SerializeError
class SerializeError(Exception):
"""Error in serialized tree"""
pass
You don't need to write this code under your model ! Can you show your serializers.py and your views.py please
I have noticed that prompt using click accepts inputs with trailing spaces
ftp_server = click.prompt("FTP Server")
Is there a way to use a custom return function like this to reject trailing spaces?
def custom_prompt(value):
if value.strip():
return True
else:
return False
ftp_server = click.prompt("FTP Server", custom_prompt)
I have already used this:
while not ftp_server.strip():
ftp_server = click.prompt("FTP Server")
But I'm looking for a better way because I don't want to use a while loop each time I use prompt.
To reject invalid user input, you can use the value_proc parameter to click.prompt. A validator to reject input with trailing spaces could look like:
Prompt Validator
import click
def validate_no_trailing_space(value):
if value != value.rstrip():
raise click.UsageError("Trailing space is invalid!")
return value
ftp_server = click.prompt("FTP Server",
value_proc=validate_no_trailing_space)
Trim Spaces
You might also consider a validator which trims leading and trailing spaces but reject spaces in the name:
def validate_no_internal_space(value):
value = value.strip()
if ' ' in value:
raise click.UsageError("Spaces are not valid here!")
return value
I'm trying to validate the values in the model and get as output the validated values. The only example in the documentation is the following code, which doesn't show how exactly this is done so I can't extend on it.
>>> from schematics.models import Model
>>> from schematics.types import StringType, BooleanType
>>> from schematics.exceptions import ValidationError
>>>
>>> class Signup(Model):
... name = StringType()
... call_me = BooleanType(default=False)
... def validate_call_me(self, data, value):
... if data['name'] == u'Brad' and data['call_me'] is True:
... raise ValidationError(u'He prefers email.')
... return value
...
>>> Signup({'name': u'Brad'}).validate()
>>> Signup({'name': u'Brad', 'call_me': True}).validate()
Traceback (most recent call last):
...
ModelValidationError: {'call_me': [u'He prefers email.']}
I made a version of it but removed data and value from arguments. Client is the name of my model. So when I do the following I get the desired result as output:
client.validate_client(client.to_native())
However,
first of all, this doesn't seem a clean way. client already has all the values and so I wouldn't need to do this.
Also, I like to get this to update the values of client as an outcome of validation.
For the first part, I did something line this:
def validate_client(self):
data = self.to_native()
...
return data
But I don't think this is the best way to do this and I am not sure about the second issue of updating the values. Is there a way to do this?
EDIT:
This is the code I have and I want the client value for employer to be set to 'unspecified' and client full_name to be set as specified in the function.
class LowerCaseEmailType(EmailType):
def convert(self, value, context=None):
value = super(LowerCaseEmailType, self).convert(value, context)
return value.lower()
class CleanedStringType(StringType):
converters = []
def __init__(self, **kwargs):
"""
This takes in all the inputs as String Type, but takes in an extra
input called converters.
Converters must be a list of functions, and each of those functions
must take in exactly 1 value , and return the transformed input
"""
if 'converters' in kwargs:
self.converters = kwargs['converters']
del kwargs['converters']
super(CleanedStringType, self).__init__(**kwargs)
def convert(self, value, context=None):
value = super(CleanedStringType, self).convert(value, context)
for func in self.converters:
value = func(value)
return value # will have a value after going through all the conversions in order
class Client(Model):
"""
Client Model
"""
first_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!##$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
last_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!##$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
full_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!##$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
employer = StringType(required=False)
created = StringType(default=" ")
updated = StringType(default=" ")
email = LowerCaseEmailType(required=False)
def validate_client(self):
data = self.to_native()
if data.get('first_name') and data.get('last_name'):
data['full_name'] = ' '.join([data['first_name'], data['last_name']])
if data.get('full_name') is None:
if data.get('first_name') is None:
error_message = 'first name missing'
else:
error_message = 'last name missing'
logger.error('info: {} for {}'.format(error_message, data))
raise ValidationError(error_message)
if data.get('employer') is None:
logger.warning('info: employer missing for {}'.format(data))
data['employer'] = 'unspecified'
return data
I think you want pre_setattr. It is called with the value when you set a value of a model (code in question).
For the eymployer I think you want to set a default. To me this seems to behave exactly as you want.
I think fullname should not be on the model, because you can have inconsistent data where firstname + lastname != fullname. If you need it later you could implement that via #serialized.
Within clean(), I am attempting to check if the User included "#" in the SearchHashtagForm and, if so, remove it.
For example, assume that User enters "#foo" on the SearchHashtagForm:
EXPECTED 'search_text': "foo"
ACTUAL 'search_text': "#foo"
I suspect that the line: form_input = form_input[1:] doesn't work, but I'm not sure what else to use?
Views.py
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
def form_valid(self, form):
form.clean()
return super().form_valid(form)
Forms.py
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean(self):
cleaned_data = self.cleaned_data
form_input = cleaned_data.get('search_text')
if form_input.startswith('#'): # if input starts with '#', remove it.
form_input = form_input[1:]
cleaned_data['search_text'] = form_input
return cleaned_data
SOLVED
In the interests of being succinct, I omitted the line: self.get_tweets(form) from form_valid() from the original query. I have provided by a more complete copy of the code, along with the solution, below:
As the solution, I removed clean() and instead included lstrip("#") (as suggested by below) in both get_success_url and get_tweets().
def get_success_url(self):
return '{}?search_text={}'.format(
reverse('mapping_twitter:results'),
self.request.POST.get('search_text').lower().lstrip("#"),
)
def form_valid(self, form):
self.get_tweets(form)
return super().form_valid(form)
def get_tweets(self, form):
...
search_filter = self.request.POST.get('search_text').lower().lstrip("#")
...
tweet_object, created = Hashtag.objects.get_or_create(search_text=search_filter)
...
You may use lstrip(), to remove the unwanted characters from the starting of your string as:
>>> tag = "#foo"
>>> tag.lstrip("#")
>>> "foo"
>>> tag = "foo"
>>> tag.lstrip("#")
>>> "foo"
>>> tag = "#foo#bar"
>>> tag.lstrip("#")
>>> "foo#bar"
This will also save you the extra method calls to check if the string starts with "#" or not, it implicitly handles it and does nothing if the tag does not start with the desired "#".
if form_input = form_input[1:] and form_input.startswith('#') don't throw errors,
Maybe you've got a normal string (else Idk why slicing and .startswith('#') should work) that starts with n invisible trailing characters before the # you see.
if thats the case, just try :
form_input = form_input[2:]
form_input = form_input[3:]
form_input = form_input[4:]
...
and see if you get reasonable results.
(print form_input and see what comes out)
if this does not work, you most likely have some werid datatype in form input.
obtain type and value of form input and add those to your question.
You can try this too:
''.join(filter(lambda x: x != '#', '#foo'))
# foo
You can use regular expression for this
import re
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean(self):
cleaned_data = self.cleaned_data
form_input = cleaned_data.get('search_text')
re.sub('[#]','', form_input)
cleaned_data['search_text'] = form_input
return cleaned_data
This will replace all the characters in the string matching '#'. This solution is more robust since you can check for more characters like "%". for instance
re.sub('[#%]','', form_input)
I seem to have a mistake in my validator. Even when I enter -1 in my form I still get my value returned instead of blaat. Perchance someone sees my mistake?
class test:
def __init__(self):
self.render = web.template.render('templates/')
self.myForm = web.form.Form(
web.form.Textbox('minutes', id='minutes'),
validators = [form.Validator("Minutes not correct",
lambda i: i.minutes > 0)]
)
def GET(self):
return self.render.addLog(self.myForm)
def POST(self):
webinput = web.input()
if self.myForm.validates():
return webinput.date1+webinput.minutes
else:
return "blaat"
i.minutes won't be converted to int automatically, and strings compare greater than integers:
>>> '-1' > 0
True
Use int(i.munites)
By the way, form-wide validators are used to compare form fields between each other, e.g. to check that the entered passwords match. To check if any given field is correct, use one-field validators:
self.myForm = web.form.Form(
web.form.Textbox('minutes',
web.form.Validator("Minutes not correct", lambda x: int(x) > 0)),
)