バリデータとウィジェット |フォーム処理の抽象化
テンプレートエンジンやO/Rマッパーを作ることで、Webアプリケーションのプログラムがシンプルになりました。ここでは、高度で使いやすいWebアプリケーションに欠かせないフォームの処理をより手軽に作る方法について考えてみたいと思います。
バリデータの利用
データの入力を行うWebアプリケーションでは、入力値のチェック処理が欠かせません。フォームのようなUIに入力された値をプログラムの側でチェックし、期待される値が入力されているかどうかを確かめるわけです。このような処理はバリデーション(妥当性)チェックと呼ばれています。
たとえば、Webアプリケーションを使ってアンケートを集めるとします。アンケート項目と一緒にメールアドレスを入力してもらい、アンケート入力後に確認のメールを送るようにしたいとします。もちろん、入力された項目はデータベースに保存します。
WebアプリケーションのUIとなるフォームにはどのような文字列も入力できます。間違えて、メールアドレスとしてふさわしくない文字列が入力されるかもしれません。そのような値が登録されてしまうと、メールが送れなくなってしまいます。そうならないためにも、メールアドレスが文字列として正しいかを事前にチェックする必要があります。
また、Webのフォームは未入力の項目があっても送信できてしまいます。名前や住所のように、必ず入力してもらいたい項目があっても、空のままリクエストをPOSTできます。フォームに必須項目がある場合は、値が入力されているかどうかを事前にチェックする必要があります。空項目のチェックも重要なバリデーションチェックの1つです。
メールアドレスのバリデーションチェック
バリデーションチェックという長く難しそうな名前が付いていますが、実際に行うことは文字列の検査にすぎません。リクエストのクエリにある文字列を調べて、正しい文字列で構成されているかを調べるわけです。
たとえば、数値だけ入力できる項目であれば文字列が数字だけで構成されているかどうかを調べます。文字列メソッドのisdigit()を使うことでそのような条件を検査できます。URLとして正しい文字列であることを簡易確認するためには、クエリ文字列が「http://」で始まっているかどうかを調べればよいでしょう。文字列の最初を調べるには、startswith()というメソッドを利用します。
メールアドレスのように、一定のパターンや条件を持った文字列を調べるには正規表現を使います。メールアドレスの形式や、どのような文字列が使えるのかについては「RFC2822」という文書に細かく定義されています。厳密にメールアドレスを判別するのは実は難しいのですが、簡易に判別するのであれば正規表現を使うとよいでしょう。
インタラクティブシェルで試してみましょう。メールアドレスとして妥当な文字列をsearch()メソッドに渡すと、Matchオブジェクトが返ってきます。形式が整っていない、不正な文字列が混入しているなど、メールアドレスとして正しくない文字列の場合はNoneが返ってくるため、インタラクティブシェルにはなにも表示されません。
:::python
>>> import re
>>> pat=re.compile('[0-9a-z_&.+-]+@([0-9a-z-]+¥.)+[0-9a-z-]+$') >>> pat.search('guidop@python.org')
<_sre.SRE_Match object at 0x1268e20>
>>> pat.search('foobarbaz')
>>> pat.search('foo@bar')
>>>
メールアドレスだけでなく、URL相当の文字列を厳密に検査したい場合にも正規表現が利用できます。また、文字列がユニコードのカタカナだけで構成されているかどうか、といった条件も正規表現を利用して確認できます。
バリデータとは
文字列オブジェクトのメソッドや正規表現を利用すれば、入力値のバリデーションチェックは可能です。これまでのサンプルプログラムでは、そのような方法を使ってバリデーションチェックを行っていました。
しかし、このような方法でバリデーションチェックを行う場合、似たような処理が複数の部分に出てきて、コードが冗長になってしまう場合があります。バリデーションチェックにはいくつかの典型的なパターンがあります。空項目のチェック、数値に変換できる文字列かどうか、メールアドレスやURLとして正しい文字列かどうか、などがよく使われるパターンの例です。バリデーションチェックにはパターンがあるわけですから、クラスやモジュールとして実装しておけば、繰り返し利用できるようになります。コードの重複も防げるようになります。
バリデーションチェックの処理を抽象化し、典型的な処理を手軽に実行する目的で利用するのがバリデータです。バリデータは、チェックを行う文字列などのオブジェクトを受け取り、期待通りの値であるかどうかを確かめて結果を返します。