Is there any way to strip surrounding whitespace from all values in WTForms without adding a filter to every single field?
Currently I'm passing filters=[strip_whitespace]
with the function shown below to my fields but having to repeat this for every field is quite ugly.
def strip_whitespace(s):
if isinstance(s, basestring):
s = s.strip()
return s
A solution requiring subclassing of Form
would be fine since I'm already doing that in my application.
You can do it in WTForms 2.x by using the bind_field primitive on class Meta
. The class Meta paradigm is a way to override WTForms behaviors in contexts such as binding/instantiating fields, rendering fields, and more.
Because anything overridden in class Meta
defined on a Form is inherited to any form subclasses, you can use it to set up a base form class with your desired behaviors:
class MyBaseForm(Form):
class Meta:
def bind_field(self, form, unbound_field, options):
filters = unbound_field.kwargs.get('filters', [])
filters.append(my_strip_filter)
return unbound_field.bind(form=form, filters=filters, **options)
def my_strip_filter(value):
if value is not None and hasattr(value, 'strip'):
return value.strip()
return value
Now, just inherit MyBaseForm
for all your forms and you're good to go.
Unfortunately, I have no enough reputation to comment first response. But, there is extremely unpleasant bug in that example: When you do filters.append(smth) then on each form initialization filters growth by 1 element. As a result, your code works slower and slower until you restart it
Consider Example:
class MyBaseForm(Form):
class Meta:
def bind_field(self, form, unbound_field, options):
filters = unbound_field.kwargs.get('filters', [])
filters.append(my_strip_filter)
return unbound_field.bind(form=form, filters=filters, **options)
def my_strip_filter(value):
if value is not None and hasattr(value, 'strip'):
return value.strip()
return value
class MyCustomForm(MyBaseForm):
some_field = StringField(filters=[lambda x: x])
for i in range(100):
MyCustomForm(MultiDict({'some_field': 'erer'}))
print(len(MyCustomForm.some_field.kwargs['filters'])) # print: 101
So the fast fix is to check that this filter not in list:
class MyBaseForm(Form):
class Meta:
def bind_field(self, form, unbound_field, options):
filters = unbound_field.kwargs.get('filters', [])
if my_strip_filter not in filters:
filters.append(my_strip_filter)
return unbound_field.bind(form=form, filters=filters, **options)
I wouldn't be surprised if you could do it by subclassing form, but my solution was to just create custom Stripped* fields. I think this is at least better than passing filters every time because it is less error prone:
from wtforms import StringField, PasswordField
class Stripped(object):
def process_formdata(self, valuelist):
if valuelist:
self.data = valuelist[0].strip()
else:
self.data = ''
class StrippedStringField(Stripped, StringField): pass
class StrippedPasswordField(Stripped, PasswordField): pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With