我正在尝试为我的烧瓶应用程序编写一个自定义验证器(我使用的是wtforms
(。我需要用户输入一个浮点值数组。我想承认的一个有效输入是,例如:
0.2, 0.35, 1, 2.0
或
12, 0.519, 8.7, 3, 9.999
由于数组的大小不是固定的,所以我考虑使用普通的StringField
,并使用,
作为分隔符来解析输入。
class PostForm(FlaskForm):
# ...
ar_params = StringField('AR parameters', validators=[DataRequired()])
# ...
submit = SubmitField('Generate Plot')
def validate_ar_params(self, ar_params):
# ... What should I write here?
raise ValidationError('Invalid input. Please insert all coefficients separated by a , (e.g. 0.2, 0.35, 1, 2.0)')
如何创建此自定义验证器?我找到了Regexr,但我不知道如何在这种情况下使用它。。。此外,是否已经实现了一种方法来从用户那里获得此输入,而不是使用StringField
和解析数据?
您可以以任何方式处理StringField
的内容,以确保输入有效,并在输入无效时引发ValidationError
。我实现了您使用,
作为分隔符来分割输入的想法:
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, ValidationError
class PostForm(FlaskForm):
# ...
ar_params = StringField('AR parameters', validators=[DataRequired()])
# ...
submit = SubmitField('GeneratePlot')
def validate_ar_params(self, ar_params):
try:
# try to convert each part of the input to a float
# see https://stackoverflow.com/a/736050/3388491
[float(x) for x in ar_params.data.split(',')]
except ValueError:
raise ValidationError('Invalid input. Please...')
看看链接SO线程中第二高的答案,然后考虑单元测试。我将您的代码作为BluePrint
添加到我的一个项目中,并在pytest设置(conftest.py
(的基础上构建:
import pytest
from app import create_app, db
class TestConfig(object):
TESTING = True
WTF_CSRF_ENABLED = False
SECRET_KEY = 'test'
SQLALCHEMY_DATABASE_URI = 'sqlite://'
SQLALCHEMY_TRACK_MODIFICATIONS = False
@pytest.fixture
def app():
"""Create and configure a new app instance for each test."""
app = create_app(TestConfig)
with app.app_context():
db.create_all()
yield app
db.session.remove()
db.drop_all()
@pytest.fixture
def client(app):
"""A test client for the app."""
return app.test_client()
有了配置和固定装置,您就可以编写测试(test_floatarray.py
(:
import pytest
def test_get_floatarray_shows_form(client):
response = client.get('/floatarray')
assert response.status_code == 200
assert b'GeneratePlot' in response.data
@pytest.mark.parametrize('data', (
'0.2',
'0.2, 0.35, 1, 2.0',
'12, 0.519, 8.7, 3, 9.999'
))
def test_valid_input_is_accepted(client, data):
response = client.post('/floatarray', data={'ar_params': data})
assert response.status_code == 200
assert f'ar_params = {data}'.encode('utf-8') in response.data
assert b'Invalid input' not in response.data
@pytest.mark.parametrize('data', (
'0.a',
'NULL',
'-+1',
'(1)',
'abc'
))
def test_invalid_input_is_rejected(client, data):
response = client.post('/floatarray', data={'ar_params': data})
assert response.status_code == 200
assert b'Invalid input' in response.data
并通过IDE或CLI:执行它们
(venv) $ python -m pytest tests/test_floatarray.py
================================== test session starts ==================================
platform darwin -- Python 3.6.5, pytest-6.1.0, py-1.9.0, pluggy-0.13.1
rootdir: /Users/oschlueter/my-project
plugins: cov-2.10.1
collected 9 items
tests/test_floatarray.py ......... [100%]
=================================== 9 passed in 1.04s ===================================