フォームモジュールは、いったん使い方を学んだら、多くの時間を費やしたりトラブルを避けることができます。
これらの時間の多くが、以下のことをやりたいためだと思います。
そして、おそらくあなたは以下のような振る舞いをフォームに持たせたいと思っているでしょう:
フォームモジュールがどのようにあなたの助けになるか見ていきましょう。。。
このモジュールは4つのCherryClassを定義します:
function: __init__(label, name, typ, mask=None, mandatory=0, size=15, optionList=[], defaultValue='', validate=None)
labelはフィールドのとなりに表示される文字列です。
nameはフィールド名を格納した文字列です。
typはフィールドのタイプを格納した文字列です。これは以下の内の一つとなります: text, password, file, hidden, submit, image, select, textarea, radio, checkbox
maskはフィールドを表示するために使われるマスクです。デフォルト値はdefaultFormMask.defaultMaskです。maskはFormFieldインスタンスを引数として受け取り、これはフィールドを表示するためになんらかのHTMLを返すはずです。
mandatoryはフィールドが入力必須か否かを示す整数です。
sizeはフィールドのサイズを示す整数です。
mandatoryはフィールドが入力必須か否かを指し示す整数です(これはテキストやパスワードなどのようなフィールドのためだけに使われます)
optionListはフィールドの異なるオプションを格納する文字列のリストです(ラジオボックスかチェックボックスフィールドのためだけに使われます)。
validateはフィールドが有効かどうかを確認するために使われる関数です。この関数はフィールドの値を引数として受け取り、もし値が適切であればNoneを返し、もし値が不適切であればエラーメッセージが入った文字列を返します。
function: __init__(label, mask)
labelは何を表示するかを知るためにmaskによって使われる文字列です。
maskはフィールドを表示するために使われるマスクです。このmaskはFormSeparotrインスタンスを引数として受け取り、セパレータを表示するためになんらかのHTMLを返します。
これがモジュールのメインのCherryClassです。フォールを作成するために、Formから継承したCherryClassを宣言します。
以下の変数とメソッドを使います:
variable: method
フォームタグのmethod属性を格納した文字列です。これはsendかpostのはずです。デフォルト値はpostです。
variable: enctype
フォームタグのenctype属性を格納した文字列です。たとえば、ユーザーがファイルをアップロードできるようなフォームのために、multipart/form-dataを使うということです。デフォルト値は空文字列で、これらenctype属性が無視されたことを意味します。
variable: fieldList
FormFieldとFormInstance CherryClassのインスタンスが入っているリストです。このリストはどのフィールドとセパレータが表示されるかを決め、その順番を決定するものです。fieldListはCherryClassの__init__メソッド内にセットします。
function: formView(leaveValues=0)
この関数はフォームのHTMLコードを返します。もしleaveValuesがfalseだったら、各フィールドはデフォルト値をとります。もしleaveValuesがtrueであれば、request.paramMap内の値を使います(言い替えると、この値はユーザーによって入力されたものです)。
function: validateFields()
もしあなたが同時にいくつかのフィールドを呼び出し有効かどうか確認を実行する必要がある場合(例えば、2ぐのパスワードが一致するかどうかをチェックする)、この関数は上書きされます。
もしフィールドがエラーである場合、この関数はFormFieldインスタンスのerrorMessageメンバ変数をセットします。
function: setFieldErrorMessage(fieldName, errorMessage)
fieldNameという名前のFormFieldインスタンスのerrorMessageメンバ変数をセットします。
function: getFieldOptionList(fieldName)
fieldNameという名前のFormFieldインスタンスのoptionListメンバ変数をセットします。
function: getFieldDefaultValue(fieldName)
fieldNameという名前のFormFieldインスタンスのdefaultValueメンバ変数をセットします。
function: setFieldDefaultValue(fieldName, defaultValue)
fieldNmaeという名前のFormFieldインスタンスのdefaultValueメンバ変数をセットします。
function: getFieldNameList(exceptList=[])
fieldListメンバ変数に基づいて、フィールド名のリストを返します。exceptList内の名前は無視されます。
function: validateForm()
この関数はユーザーが入力したデータが適切か不適切なデータかどうかをチェックします。適切であれば1を返し、そうでなければ2を返します。
view: postForm(**kw)
このviewはユーザーがフォームをsubmitした時に自動敵に呼び出されます。フォームデータを扱うため、このviewを上書きしたりコードを追加したりすることができます。このviewの典型例は以下ようなものです:
def postForm(self, **kw): if self.validateForm(): # Yes, the data is correct # Do what you want here pass else: # No, the data is incorrect # Redisplay the form and tell the user to fix the errors: return "<html><body><font color=red>Fill out missing fields</font>"+self.formView(1)+"</body></html>"
フォームmaskはFormFieldインスタンスを入力としてとり、HTMLコードを出力として返します。あなたのmaskがcurrentValueメンバ変数にしたがってフィールドの値をセットすることを忘れないでください。さらに、errorMessageがセットされているかどうかでフィールドの扱いが違います。
例えば、選択ボックスについて、マスクは以下のようになります:
if field.typ=='select': result='%s: <select name="%s" size="%s">'%(field.label, field.name, field.size) for optionValue in optionList: if optionValue==field.currentValue: checked=' checked' else: checked='' result+='<option%s>%s</option>'%(checked,optionValue) result+='</select> if field.errorMessage: result+=' <font color=red>%s</font>'%field.errorMessage return result+'<br>'
すてきなフォームを作成するために、これらのCherryClass、変数、メソッドの使い方をみていきましょう。
ユーザーがログインやパスワードを選択し、e-mailを入力したり、住んでいる国や、趣味を入力するフォームを作成することにします。
これには6つのフィールドが必要です:
これに加え、e-mailフィールドと住んでいる国のフィールドの間に一行入れることにします。
以下のようなコードになります:
use Form, MaskTools # We start by creating a CherryClass that inherits from Form # This CherryClass will hold all the informations about the form we want to create CherryClass MyForm(Form): function: def __init__(self): # Instantiate all fields plus 3 separators (one at the beginning, one for the line and one a t the end) headerSep=FormSeparator('', defaultFormMask.defaultHeader) login=FormField(label='Login:', name='login', mandatory=1, typ='text') password=FormField(label='Password:', name='password', mandatory=1, typ='password') password2=FormField(label='Confirm password:', name='password2', mandatory=1, typ='password' ) email=FormField(label='E-mail:', name='email', typ='text', validate=self.validateEmail) lineSep=FormSeparator('', self.lineSeparator) country=FormField(label='Country:', name='country', typ='select', optionList=['USA', 'Andorr a', 'Lichtenstein', 'CherryPyLand'], defaultValue='USA') hobbies=FormField(label='Hobbies:', name='hobbies', typ='checkbox', optionList=['Using Cherr yPy', 'Eating Cherry Pie']) submit=FormField(label='', name='Submit', typ='submit') footerSep=FormSeparator('', defaultFormMask.defaultFooter) self.fieldList=[headerSep, login, password, password2, email, lineSep, country, hobbies, sub mit, footerSep] # Function that checks if an e-mail is correct or not def validateEmail(self, email): try: before, after=email.split('@') if not before or after.find('.')==-1: raise 'Error' except: return "Wrong email" # Function that performs general validation of the form. In our case, we need to check # that the passwords match def validateFields(self): # Warning: paramMap could have no "password" or "password2" key if the user didn't fill out the fields if request.paramMap.get('password','')!=request.paramMap.get('password2',''): # Set errorMessage for password fields self.setFieldErrorMessage('password', 'Not matching') self.setFieldErrorMessage('password2', 'Not matching') mask: # Line separator used to draw a line between the email field and the country field def lineSeparator(self, label): <tr><td colspan=3 height=1 bgColor=black py-eval="maskTools.x()"></td></tr> view: def postForm(self, **kw): if self.validateForm(): return root.formOk() else: return "<html><body><font color=red>Please correct the errors (fields in red)</font>"+se lf.formView(1)+"</body></html>" # Now we just have to create a regular Root CherryClass, that will call some of MyForm's methods CherryClass Root: mask: def index(self): <html><body> Welcome, please fill out the form below: <py-eval="myForm.formView()"> </body></html> def formOk(self): <html><body> Thank you for filling out the form.<br> All values were correct </body></html>