フォームクラスは、ルールに対して送信されたデータを対象としています(IMO)。例:パスワードは等しいか、終了日が開始日より遅いか。
submitted data--->|Form|
フォームクラスが、データベースから取得したデータに対して送信されたデータを検証しても問題ありませんか?これは責任の問題のようです。Formクラスは送信の検証とクリーニングのみを担当する必要があり、DBに対するチェックはクラスの外部に属します。
submitted data--->|Form|<---data from DB
PythonのWTFormsでの私の例を次に示します。ユーザーIDが整数であるかどうかを確認し、DBにクエリを実行して存在を確認します。
class ClientForm(Form):
name = StringField(validators=[DataRequired(message="Invalid value")])
user = IntegerField(validators=[DataRequired(message="Invalid value")])
zone = IntegerField(validators=[AnyOf([i[0] for i in ZONES], message="Invalid value")])
#validate user as real
def validate_user(form, field):
user = db.session.query(User).filter(User.id==form.user.data).first()
if not user:
raise ValidationError('Invalid user')
このチェックをフォームに追加することの利点は便利です。WTFormsはエラーのすべての側面を処理し、それらをレンダリングします。
form = ClientForm(post_data)
if not form.validate():
# render the form again with errors highlighted
return render("client_registration_form.html", form=form)
else:
return render("success.html")
データベースを直接参照することにより、特にグローバルからデータベースを取得することにより、プレゼンテーションレイヤーと永続性レイヤーを密に結合しています。代わりに、SOLIDの原則に目を向けて、この問題に取り組む必要があります。
グローバルオブジェクトに到達してデータベース接続を取得する代わりに、その依存関係をフォームバリデーターに注入する必要があります。このようにして、グローバルな状態の一部の具体化ではなく、データベースの抽象化に依存することができます。依存関係を交換できるため、コードはより柔軟でテスト可能になります。
これを実現するためのより良い方法は、データベースからフォーム検証を完全に分離するための中間オブジェクトを作成することです。この中間オブジェクトには、データベース接続が挿入され、フォームバリデーターに挿入されます。これにより、フォームバリデーターに柔軟な依存関係を持たせることができます。次のようになります。
class UserIDExists:
def __init__(self, db):
self["db"] = db
def check(self, user_id):
user = db.session.query(User).filter(User.id == user_id).first()
return bool(user)
次に、WTFormsクラスはcheck
メソッドを使用して、レイズするかどうかを決定します。
しかし、さらに良い方法があります。任意のクラスを作成する代わりに、 カスタムWTFormsバリデーター であるクラスを作成できます。それでも注入しますが、すでに使用している他のバリデーターと、はるかにクリーンでシームレスな方法で統合されます。
WTFormsを使用して、ユーザーが直接送信していないデータを検証しても問題ないと思います。データベースのデータを検証するのは非常に奇妙に思えます。データベースとDALはすでにデータを検証しているはずです。
WTFormsを使用して、ユーザーが送信したデータとデータベースからのデータの組み合わせを検証することは不合理ではありません。それでも、インタラクティブフォームの場合は、データベースの内容に基づいて、その構造自体が無効なデータの入力を防止するフォームをユーザーに表示してもらいたいと思います。おそらく、それが不可能または実用的でない場合があります。
WTFormsを使用してデータを検証していることが簡単にわかります。解析された入力ファイルなど、フォーム送信ではない外部システム。