Reputation: 665
When using pytest to do unittesting on posting datas to flask wtforms, the form's fileds' data is always ''
, which seems like the data is not properly "posted" to the forms, and it cause the form.validate_on_submit()
will always return False
. I've disabled the WTF_CSRF_ENABLED
when testing.
I've made a minimal project to demonstrate this problem. I did not include database here because database works fine in my real project.
This minimal project structure is here:
.
├── app.py
├── templates
│ └── login.html
└── tests
└── test_login.py
test_login.py:
import unittest
from flask import current_app
from app import create_app
class BasicsTestCase(unittest.TestCase):
def setUp(self):
self.app = create_app()
self.app.config['WTF_CSRF_ENABLED'] = False
self.app_context = self.app.app_context()
self.app_context.push()
self.client = self.app.test_client()
def tearDown(self):
self.app_context.pop()
def test_app_exists(self):
self.assertFalse(current_app is None)
def test_home_page(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
def test_login(self):
response = self.client.post(
'/login', data={
'username': 'a',
'password': 'a'
})
app.py:
from flask import Flask, redirect, render_template, url_for, Blueprint
from flask_wtf import FlaskForm
from wtforms import PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired, Length
bp = Blueprint('myapp', __name__)
@bp.route('/')
def home():
return 'hello'
@bp.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(prefix='form-login-')
if form.validate_on_submit():
return redirect(url_for('home'))
return render_template('login.html', form=form)
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Log In')
def create_app():
app = Flask('__name__')
app.config['SECRET_KEY'] = 'secretkey'
app.register_blueprint(bp)
return app
Upvotes: 0
Views: 1315
Reputation: 665
It turns out that when your wtforms have the prefix
property, the way you post data should change.
As you see, the form I use is form = LoginForm(prefix='form-login-')
, and the way I post the data to the form is
response = self.client.post(
'/login', data={
'username': 'a',
'password': 'a'
})
It will not pass data properly until you add the prefix
you use in the form to the data dictionary, like this:
response = self.client.post(
'/login', data={
'form-login-username': 'a',
'form-login-password': 'a'
})
Everything works fine now!
But if you want to get the form field data, you should still use form.username.data
, without any prefix
.
Upvotes: 2