wtformsを使用してサインアップフォームを作成しました。フォームの要素の一部を再度繰り返す必要がないように、FormFieldを使用しています。ただし、[送信]ボタンをクリックすると、validate_on_submitメソッドの呼び出しで常にfalseが表示されます。なぜこれが起こっているのかわからない。
私form.py
は次のとおりです。
class ProfileInfoForm(Form):
firstname = TextField('firstname', validators=
[validators.Required("Please enter First name.")])
lastname = TextField('lastname', validators=
[validators.Required("Please enter Last name.")])
email = EmailField('email', validators=
[validators.Required("Please enter your valid email.")])
gender = RadioField('gender', validators=
[validators.Required("Please select gender")],
choices=[('female', 'Female'), ('male', 'Male')])
dob = TextField('dob', validators=
[validators.Required("Please select date of birth.")])
languages = SelectMultipleField('languages', choices=[('', '')],
validators=
[validators.Required("Please select\
atleast one \
language.")])
class RegistrationForm(Form):
profilefield = FormField(ProfileInfoForm)
password = PasswordField('password',
validators=
[validators.Required("Please enter password."),
validators.Length(min=8),
validators.EqualTo('confirm_password',
message='Password and confirm\
password must match')])
confirm_password = PasswordField('confirm_password',
validators=
[validators.Required("Please enter\
confirm password.")])
tnc = BooleanField('tnc', validators=
[validators.Required("Please select Terms and \
Conditions")], default=False)
submit = SubmitField('Create My Account')
Signup
方法は次のとおりです。
@module.route('/signup', methods=['GET', 'POST'])
@handle_error
def signup():
if hasattr(g, 'user') and g.user:
# TODO: do some operations if needed else keep it blank
return redirect(url_for('index'))
else:
signup_form = RegistrationForm()
# Add choices for the user
signup_form.profilefield.languages.choices = getLanguages()
if signup_form.validate_on_submit():
firstname = signup_form.profilefield.firstname.data
lastname = signup_form.profilefield.lastname.data
email = signup_form.profilefield.email.data
password = signup_form.password.data
# confirm_password = signup_form.confirm_password.data
gender = signup_form.profilefield.gender.data
dob = signup_form.profilefield.dob.data
languages = signup_form.profilefield.languages.data
tnc = signup_form.tnc.data
payload = {'firstname': firstname, 'lastname': lastname,
'email': email, 'password': password, 'gender': gender,
'dob': dob, 'languages': languages,
'tnc': ('1' if tnc else '0')}
try:
buildApiUrl = BuildApiUrl()
response = requests.post(buildApiUrl.getUrl("user", "signup"),
data=payload)
if response.status_code == requests.codes.ok:
data = json.loads(response.text)
if 'status' in data and data['status'] != 200:
flash(data['message'], category="error")
else:
flash(data['message'] +
': Your account is created successfully! ' +
'Please login to your account!',
category="success")
return redirect(url_for('index'))
except requests.exceptions.RequestException:
flash('Internal Server side error occured', category="error")
return redirect(url_for('server_error', e='500'))
return render_template('public/index.html',
signup_form=signup_form, login_form=LoginForm())
HTMLフォームはここの要点にあります
参考:必要なすべてのフィールドに、実際に必要なデータを入力しています。validate_on_submit()を呼び出すと、まだfalseになります。私のコードの何が問題になっていますか?
編集:getLanguagesは、データベースから言語を取得して選択リストに入れるメソッドです。この機能は期待どおりに行われており、言語のリストを取得できます。
編集2:ここで1つのことを実現します。これはFormFieldが原因で発生しています。これは、ProfileInfoForm()のすべてのフィールドをRegistrationForm()メソッドに追加してテストしたところ、すべてが正常に機能し、サインアップできたためです。そのため、FormFieldまたはその使用方法に問題がありますが、どこで問題が発生しているかはわかりません。
問題はFormFieldではなく、私のProfileInfoForm()にあることがわかりました。常にfalseを返します。まだ理由はわかりませんが、そのことについては自分で検証を書かなければならないかもしれません。何かご意見は?
編集:
ダンプで私は次のようになりました(ここでpprintを使用しました):
{'SECRET_KEY': '1e4c35233e50840483467e8d6cfe556c',
'_errors': None,
'_fields': {'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>},
'_prefix': u'profilefield-',
'csrf_enabled': True,
'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>}
編集:
少し掘り下げてみると、エラーが生成されるのはcsrfトークンがないことが原因であることがわかりました。しかし、私は{{ signup_form.hidden_tag() }}
htmlのフォームテンプレートに含めました。また、要素を検査すると生成されたhtmlに非表示のタグが表示され、ハッシュ値を含むcsrf_tokenフィールドが表示されます。では、ここで何が問題になっていますか?
次の関数で問題を解決しました。
def __init__(self, *args, **kwargs):
kwargs['csrf_enabled'] = False
super(ProfileInfoForm, self).__init__(*args, **kwargs)
この関数をに追加しました ProfileInfoForm()
問題はFormField
、csrf_token
フィールドと実際のフォームが含まれていることRegistrationForm
でした。つまり、csrf_tokenも含まれcsrf_token
ていたため、検証する必要があるのは2つで、実際にフォームにレンダリングされるのは1つだけでした。それで、FormFieldがそれをレンダリングcsrf_token
しProfileInfoForm
たとき、私はそれを無効にしましたcsrf_token = False
。
そして、RegistrationForm
しているんcsrf_token
フォームがまだ安全であるように、今も有効。
私の推測では、これもFormField
同様に行う必要があります。
参考:FormFieldコードの解釈が原因で、このソリューションは間違っている可能性があります。したがって、上記の解決策が間違っている場合は、訂正してください。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加