103 lines
3.1 KiB
Python
103 lines
3.1 KiB
Python
from sqlalchemy.orm.exc import NoResultFound
|
|
|
|
from wtforms import ValidationError
|
|
try:
|
|
from wtforms.validators import InputRequired
|
|
except ImportError:
|
|
from wtforms.validators import Required as InputRequired
|
|
|
|
from flask_admin._compat import filter_list
|
|
|
|
|
|
class Unique(object):
|
|
"""Checks field value unicity against specified table field.
|
|
|
|
:param get_session:
|
|
A function that return a SQAlchemy Session.
|
|
:param model:
|
|
The model to check unicity against.
|
|
:param column:
|
|
The unique column.
|
|
:param message:
|
|
The error message.
|
|
"""
|
|
field_flags = ('unique', )
|
|
|
|
def __init__(self, db_session, model, column, message=None):
|
|
self.db_session = db_session
|
|
self.model = model
|
|
self.column = column
|
|
self.message = message
|
|
|
|
def __call__(self, form, field):
|
|
# databases allow multiple NULL values for unique columns
|
|
if field.data is None:
|
|
return
|
|
|
|
try:
|
|
obj = (self.db_session.query(self.model)
|
|
.filter(self.column == field.data)
|
|
.one())
|
|
|
|
if not hasattr(form, '_obj') or not form._obj == obj:
|
|
if self.message is None:
|
|
self.message = field.gettext(u'Already exists.')
|
|
raise ValidationError(self.message)
|
|
except NoResultFound:
|
|
pass
|
|
|
|
|
|
class ItemsRequired(InputRequired):
|
|
"""
|
|
A version of the ``InputRequired`` validator that works with relations,
|
|
to require a minimum number of related items.
|
|
"""
|
|
def __init__(self, min=1, message=None):
|
|
super(ItemsRequired, self).__init__(message=message)
|
|
self.min = min
|
|
|
|
def __call__(self, form, field):
|
|
items = filter_list(lambda e: not field.should_delete(e), field.entries)
|
|
if len(items) < self.min:
|
|
if self.message is None:
|
|
message = field.ngettext(
|
|
u"At least %(num)d item is required",
|
|
u"At least %(num)d items are required",
|
|
self.min
|
|
)
|
|
else:
|
|
message = self.message
|
|
|
|
raise ValidationError(message)
|
|
|
|
|
|
def valid_currency(form, field):
|
|
from sqlalchemy_utils import Currency
|
|
try:
|
|
Currency(field.data)
|
|
except (TypeError, ValueError):
|
|
raise ValidationError(field.gettext(u'Not a valid ISO currency code (e.g. USD, EUR, CNY).'))
|
|
|
|
|
|
def valid_color(form, field):
|
|
from colour import Color
|
|
try:
|
|
Color(field.data)
|
|
except (ValueError):
|
|
raise ValidationError(field.gettext(u'Not a valid color (e.g. "red", "#f00", "#ff0000").'))
|
|
|
|
|
|
class TimeZoneValidator(object):
|
|
"""
|
|
Tries to coerce a TimZone object from input data
|
|
"""
|
|
def __init__(self, coerce_function):
|
|
self.coerce_function = coerce_function
|
|
|
|
def __call__(self, form, field):
|
|
try:
|
|
self.coerce_function(str(field.data))
|
|
except Exception:
|
|
msg = u'Not a valid timezone (e.g. "America/New_York", "Africa/Johannesburg", "Asia/Singapore").'
|
|
raise ValidationError(field.gettext(msg))
|