MongoDBをWindows 7にインストールする
MongoDBをWindows 7のサービスとして登録するときに躓いたのでメモ。
全く同じ状況の人がいたので、それを参照。
Installing MongoDB on Windows 7 - Scott Blaine
そのまま解決。フルパスで入力するのと管理者権限のcmd.exe起動がキモっぽい。
でも、logみると終了してるよ?って感じだったけど、コンパネの管理ツールで起動したらオッケーだった。多分、再起動時から起動になってたのかな?
Flash-AssetsでClosure Compilerを使用する
Flash-AssetsでClosure Compilerを使用した際に躓いた箇所をメモ。
使い方などはFlask-Assets — Flask-Assets 0.8.dev documentationを参照のこと。
Windows環境でClosureを使用しようとすると、なんかエラーがでて正常に動作しない。なんだこれは!とおもって調べてみると環境変数とFlask-Assetsのファイル自体に原因があるみたい。解決策として、環境変数JAVA_HOMEにjava.exeのあるbinフォルダつまり、JAVA_HOME/bin/java.exeとなるように設定を行い、(pythonをインストールしたフォルダ)/Libsite-packages/webassets/filter/__init__.pyの322行目辺り(ver0.7)を
proc = subprocess.Popen( [self.java, '-jar', self.jar] + args, # we cannot use the in/out streams directly, as they might be # StringIO objects (which are not supported by subprocess) stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
とすれば良い。なんか、shell=Trueを追加しないとエラーが出るみたいね。
すごい雑だけど以上。
LiveValidationでID重複チェックを使う
タイトルの通り、LiveValidation - Validation as you typeでユーザーIDの重複チェックを行えるようにしてみた。
理想はTwitterの登録画面で、LiveValidationはフォームの隣にシンプルに結果を表示しているので採用した。
基本的な使い方は、
var user_id = new LiveValidation('id', {validMessage: "valid", wait: 200}); user_id.add(Validate.Presence, {failureMessage: "invalid"});
みたいな感じで、自分で作った関数を組み込むには
user_id.add(Validate.Custom, {failureMessage: "invalid", against: function(){return result}});
みたいにValidate.Customで行う。
ここから、ユーザーIDの重複機能を組み込むとなると組み込む関数の返り値が、ブール値のため確認中のメッセージを表示できないと思って一旦ドツボにはまる。解決策として、組み込む関数中にValidate.Errorで例外を投げることで対応できた。結局、グローバルな変数を使うなど下手な感じだけど完成。以下にコード。
var jqxhr = null; var old_value = null; var result = false; var error_message = 'ユーザーIDの重複をチェックしています。'; var is_duplicate = function(value, args){ if(value != old_value){ old_value = value; if(jqxhr)jqxhr.abort(); jqxhr = $.ajax({ type: "POST", url: '/check', data: {user_id: value}, success: function(data){ result = data == 'true'; args.obj.is_check = false; args.obj.validate(); } }); args.obj.is_check = true; throw new Validate.Error(error_message); } if(args.obj.is_check) throw new Validate.Error(error_message); return result; }
また、これだけだと、確認中のメッセージなどに気に入らない点があったので、LiveValidationのコードをいじるために以下を追加。
LiveValidation.prototype.is_check = false; LiveValidation.prototype.doOnFocus = function(e){ this.focused = true; } LiveValidation.prototype.insertMessage = function(elementToInsert){ this.removeMessage(); if( (this.displayMessageWhenEmpty && (this.elementType == LiveValidation.CHECKBOX || this.element.value == '')) || this.element.value != '' ){ var className = this.validationFailed ? this.invalidClass : this.validClass; if(this.is_check)elementToInsert.className += ' ' + this.messageClass; else elementToInsert.className += ' ' + this.messageClass + ' ' + className; if(this.insertAfterWhatNode.nextSibling){ this.insertAfterWhatNode.parentNode.insertBefore(elementToInsert, this.insertAfterWhatNode.nextSibling); }else{ this.insertAfterWhatNode.parentNode.appendChild(elementToInsert); } } }
そして、スタイルシートを下記のようにいじって終了。
.LV_validation_message{ color: #666666; } .LV_valid { color: #009900; } .LV_invalid { color: #CC0000; }
なんとか、フルスクラッチで作らずにすんだ・・・
WTFormsを学ぶ その3
前回の続き。
今回はフォームバリデーションについて。
WTForms Documentationの内容について勉強。
まぁ、特に変なことをしようと思ってないので、そのままドキュメント通りに書けば書いたように実装ができた。WTFormsのフォームバリデーションには正規表現によるチェックもできるので、大抵のことはできると思う。ちなみに半角英数字のチェックだと、
validators.Regexp("^[a-zA-Z0-9]+$")
でできる。
あとは、作るとしてもユーザーIDの重複チェックとかかな?
まぁ、それはおいおいということで今回はこれだけ。
WTFormsを学ぶ その2
前回の続き。
WTFormsではフォームフィールドを最初から幾つか用意してある。自分でも作れるみたいだけど、今回はそこまでのものはいらないので、TextFieldを利用。ここで、躓いたのが属性値の追加はどうすればいいか。
前回のをそのまま利用するとおそらく、
<input id="email" name="email" type="text" value="">
みたいな感じになってると思う。
それで、WTForms Documentationを読んでみると、
form.field(class_="text_blob")
上記を記述すると、
<input type="text" name="field_name" value="blah" class="text_blob" id="field_name" />
こうなって、無事にclass="text_blob"が追加されるぜハハッ!って書いてあったので、試してみたけどうまく行かなかった。何がイケないというか勘違いしてたかというと、python内のプログラムをいじってたからでした。
実際にどういう勘違いかというと、
@app.route('/register', methods=['GET', 'POST']) def register(): form = Registration(request.form) if request.method == 'POST' and form.validate(): user = User(form.username.data, form.email.data, form.password.data) return redirect(url_for('login')) return render_template('register.html', form=form)
のところに追記すればいいと思っていて、うまく行かず・・・
実際には、
{% from "_formhelpers.html" import render_field %} <form method=post action="/register"> <dl> {{ render_field(form.username) }} {{ render_field(form.email) }} {{ render_field(form.password) }} {{ render_field(form.confirm) }} {{ render_field(form.accept_tos) }} </dl> <p><input type=submit value=Register> </form>
の部分で、
render_field(form.username, class_="name")
と書かないといけないようでした。また、マクロを介さずに、
form.username(class_="name")
とテンプレートに書いても大丈夫みたい。
大した事ではないけど、躓いたのでメモ。
Sublime Text2のインデントに関して
現在、pythonでなにか書くときに使っているSublime Text 2で、テンプレート用のhtmlを書かなければいけない時があり、インデントのサイズをスペース2個分にしたかったのでメモ。
結論から言えばIndentation Settingsを見れば分かるんだけど説明すると、<syntax>.sublime-settings(<syntax>部分はファイルの種類)というファイルを作成し、内容を
{
"tab_size": 2,
"translate_tabs_to_spaces": true,
"detect_indentation": true,
"use_tab_stops": true
}
とすれば良い。
ちなみに保存するフォルダはwindows 7では、
C:\Users\ユーザー名\AppData\Roaming\Sublime Text 2\Packages\User
でいいはず。
なので、上記フォルダにHTML.sublime-settingsというファイルを作れば、後はソフト側が勝手に認識してやってくれる。
WTFormsを学ぶ その1
PythonのWebアプリケーションフレームワークであるFlaskで遊んでみたいと思い、いじってる途中でフォームについても何かあるかなと思い調べたら、WTFormsという拡張機能があるみたいなので調べてみた。
Form Validation with WTForms — Flask 0.9-dev documentation
インストールに関しては
pip install Flask-WTF
とすれば出来る。
また、自分はDotcloudの環境で利用しようとしてたので、requirements.txtに
Flask-WTF
と追記したらインストールしてくれた。ちなみにバージョンは2012/5/15現在は1.0?。
簡単な例
上記リンク先のドキュメントの例
フォームの設定
from wtforms import Form, BooleanField, PasswordField, TextField, validators class Registration(Form): username = TextField('Username', [validators.Length(min=4, max=25)]) email = TextField('Email Address', [validators.Length(min=6, max=35)]) password = PasswordField('New Password', [ validators.Required(), validators.EqualTo('confirm', message='Passwords must match') ]) confirm = PasswordField('Repeat Password') accept_tos = BooleanField('I accept the TOS', [validators.Required()])
コードから分かる通り、文字数や入力の有無、また、入力値の再入力チェックが簡単に設定できるっぽい。
ルーティングの設定
@app.route('/register', methods=['GET', 'POST']) def register(): form = Registration(request.form) if request.method == 'POST' and form.validate(): user = User(form.username.data, form.email.data, form.password.data) return redirect(url_for('login')) return render_template('register.html', form=form)
ここではPOSTリクエストを受け取ったときの処理を書いてある。form.validate()は上記のフォームの設定で行なった条件を満たしていればTrueとなる。また、受け取ったフォームの情報はform.username.dataで受け取れるみたい。
フォームのテンプレート
最初にフォーム用のフィールドとラベルの表示用のマクロを作る。ドキュメントでは_formhelpers.htmlって名前で作ってある。
{% macro render_field(field) %} <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> {% endmacro %} >|html| このマクロを設定することによって、フォームや入力不備時の表示のされ方のデザインを決めることが出来る。ドキュメントには色々書いてあるけど、読むのメンドーだから放置。で、次にフォーム自体のテンプレートをregister.htmlという名前で作成する。 >|| {% from "_formhelpers.html" import render_field %} <form method=post action="/register"> <dl> {{ render_field(form.username) }} {{ render_field(form.email) }} {{ render_field(form.password) }} {{ render_field(form.confirm) }} {{ render_field(form.accept_tos) }} </dl> <p><input type=submit value=Register> </form>
これのrender_fieldの部分が上記のマクロで設定したレイアウトで挿入される。
とりあえず基本的なことはこれでできるのかな?
もっと複雑なことをしたい場合はWTForms Documentationを参照。