I have a flask monoenginge model with a unique_with field
class RedirectMixin(object):
name = db.StringField(max_length=1000, required=True, help_text="Used internally")
matching_type = db.IntField(
help_text='`Equals` has higher priority. With concurrent `Start with` rules, longest `Url_from` wins',
required=True, choices=MATCHING_TYPES)
add_unmatched_ending = db.BooleanField(
help_text='Example: Starts with /a/ redirect to /b/. This will make /a/c/ redirect to /b/c/',
default=False)
url_from = db.StringField(max_length=1000, required=True, unique_with='matching_type',
help_text='Case insensitive')
url_to = db.StringField(max_length=1000, required=True)
what I wonder is why flask admin doesn't validate the violation of this specification (unique_with i.e) when a form is being filled on the admin side and also how else to go about the validation if flask admin is not built for it. Thanks in advance
It turns this type of validation needs interaction with the db, which flask-admin validator might not be able to provide. I created a custom validator for myself like so:
class Unique(object):
def __init__(self, with_=None, message=None):
self.message = message
self.with_ = with_
def __call__(self, form, field):
query, with_msg = {}, ''
if self.with_:
query[self.with_] = form[self.with_].data
with_msg = 'with "%s"' % self.with_
query[field.name] = field.data
if form._obj:
query['id__ne'] = form._obj.id
matched_entries = form.model_class.objects(**query)
if matched_entries:
if self.message is None:
self.message = field.gettext('Duplicate exists. Value Should be unique ' + with_msg)
raise ValueError(self.message)
is_unique = Unique
And then in my model I used it like so:
from balut.lib.forms.validators import is_unique
class RedirectMixin(object):
name = db.StringField(max_length=1000, required=True, help_text="Used internally")
matching_type = db.IntField(
help_text='`Equals` has higher priority. With concurrent `Start with` rules, longest `Url_from` wins',
required=True, choices=MATCHING_TYPES)
add_unmatched_ending = db.BooleanField(
help_text='Example: Starts with /a/ redirect to /b/. This will make /a/c/ redirect to /b/c/',
default=False)
url_from = db.StringField(max_length=1000, required=True, unique_with='matching_type',
help_text='Case insensitive')
url_to = db.StringField(max_length=1000, required=True)
form_args = dict(url_from={'validators': [is_unique(with_='matching_type', message=None)]})