アフィリエイト紹介
Webアプリの作り方からAPI化、デプロイメントまで エンジニアとデータサイエンティストのためのFlask入門は、こちら!
プログラム
サーバサイド側
cols = { 'username': StringField('Username', [validators.Length(min=4, max=25)]), 'email': StringField('Email Address', [validators.Length(min=6, max=35)]), 'password': PasswordField('New Password', [ validators.DataRequired(), validators.EqualTo('confirm', message='Passwords must match') ]), 'confirm': PasswordField('Repeat Password'), 'accept_tos': BooleanField('I accept the TOS', [validators.DataRequired()]), 'photo': FileField(validators=[ FileRequired(), FileAllowed(['py'], '.py only!') ]) } cols['add'] = IntegerField('Add', [validators.Length(min=4, max=25)]) dform = type('RegistrationForm', (FlaskForm, ), cols) form = dform() if flask.request.method == 'GET': return render_template('test/dform.html', form=form) else: if form.validate_on_submit(): return redirect(url_for('test.dform')) else: return flask.render_template('test/dform.html', form=form)
フロントエンド側(Jinja)
{% for key, value in form.__dict__.items() %} {% if is_render_field(value, 'wtforms.fields.core.Field') %} {{ render_field(value) }} {% endif %} {% endfor %}
説明
サーバサイド
1~15行目でformの項目を定義している。
17行目でRegistrationForm
というクラス名で、FlaskForm
を継承元として、メンバ変数にcols
の内容を保持したうえでクラスを動的に定義する。
18行目でクラスからインスタンスを作成する。
作成したインスタンスは事前定義したものと同じように扱える。
formの項目定義をJSONファイル等に保存しておけば、ユーザがカスタマイズできるフォーム等を作成することが可能になる。
フロントエンド
formを動的生成する場合、すべての項目を知る必要がある。
form.__dict__.items()
でformのすべてのメンバ変数にアクセスできる。
ただ、不要なものも取得してしまうので、is_render_field(value, 'wtforms.fields.core.Field')
でwtforms.fields.core.Field
を継承しているものだけを処理するようにする。
is_render_field, render_fieldは下記。
import wtforms def is_render_field(obj, _class): return isinstance(obj, eval(_class))
{% macro render_field(field) %} {% if field.label != 'CSRF Token' %} <dt>{{ field.label }} <dd>{{ field(**kwargs)|safe }} {% if field.errors %} <ul class=errors> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </dd> {% endif %} {% endmacro %}