Form libraries
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,745
On Slideshare
2,489
From Embeds
256
Number of Embeds
4

Actions

Shares
Downloads
4
Comments
0
Likes
4

Embeds 256

http://aodag.posterous.com 253
http://s.deeeki.com 1
http://localhost 1
http://a0.twimg.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. VariousWeb Form Widget Toolkits aodag Pycon JP 2011
  • 2. お前誰よ@aodag小田切篤BeProud勤務今別の部屋で発表しているianと同僚Djangoきらいです(´・ω・`) PylonsとかPyramidとか、既存のコンポーネント組み合わせてるもののほうが好きです。
  • 3. SQLAlchemy● データマッパー● すごく柔軟
  • 4. WSGI (PEP-333, PEP-3333)PythonのWebアプリケーション標準def hello(environ, start_response): start_response("200 OK", [(Content-type, text/plain)]) return ["Hello, world!"]
  • 5. AdminアプリケーションDjangoのadmin(だけ)はいいね!SQLAlchemyにも同じようなものがほしいWSGIアプリで全般的に使いたい(あまりフレームワークに依存したくない)Ajaxばりばりである必要はないけど、DatePickerとかSuggestとか、入力補助系のJSが利用できるとよい
  • 6. Adminアプリケーション● クラスごとにサブアプリケーション● グリッド表示と検索● 入力フォーム● カスタムアクションを追加できる
  • 7. フォームライブラリを調査Form Libraryの役割比較ライブラリ
  • 8. Form Libraryの役割● HTMLフォーム生成● バリデーション
  • 9. 比較ライブラリ● ToscaWidgets / Sprox● FormAlchemy● tw2.sqla● WTForms● deform/colander
  • 10. 比較のポイント● SQLAlchemyとの親和性● バリデータのカスタマイズ● フィールドのカスタマイズ● ウィジェットのカスタマイズ
  • 11. ToscaWidgets / Sprox● SproxはSQLAlchemyのスキーマからToscaWidgetsのフォームを 作成します● SQLAlchemyのスキーマ以外のフィールドをフォームに追加した り、スキーマのフィールドをフォームから削除したりできます。● formencodeでカスタムバリデータを作成します● tw.formsでカスタムフィールドを作成します
  • 12. FormAlchemy● SQLAlchemyだけでなく、zope.schemaなどにも対応● SQLAlchemyのスキーマ対応は一番すぐれている● デフォルトで用意されているウィジェットレンダラーが少ない● 実行時にもフィールド定義を変更可能● jqueryuiを使ったfa.jqueryのような追加スキンが存在する
  • 13. tw2● ToscaWidgetsの後継● まだ a4がリリースされたばかり、 発展途上● SQLAlchemyから自動生成するフォームがある ○ many-to-manyまでは対応できてない● SQLAlchemyというよりElixirに対応している
  • 14. wtforms● SQLAlchemyからのスキーマ生成はしない● SelectのoptionをSQLAlchemyのクエリで設定可能● 機能は少なめ● その分はまりどころが少なく枯れるのが早そう● フォーム全体の生成はしない● グリッド生成もしない● ToscaWidgetsのtw.formsと名前が紛らわしい><
  • 15. deform / colander ● colanderはスキーマ定義 ● deformはcolanderに対応しているフォームライブラリ ● SQLAlchemyからのスキーマ生成できない ● ウィジェットが豊富 ● ajaxとりこみに意欲的 ● deferred bindingにより実行時にウィジェットやバリデーションを変 更可能 ● テンプレートにchameleon(zope page template)を使っている ● テンプレートをmakoに入れ替えるプロジェクトが進行中http://deformdemo.repoze.org/
  • 16. Sample ModelSQLAlchemy ● User ○ user_name ○ password ○ user_image ○ groups ● Group ○ name ○ users ○ permissions ● Permission ○ name ○ groups
  • 17. ポイント● 全部many-to-manyの関連付け● User - Group - Permission● User - Permissionの派生関連付け● _password 直接見せたくないフィールド● ユーザー画像はファイル保存
  • 18. Userフォーム Sproxclass UserForm(AddRecordForm): __model__ = models.User __require_fields__ = [user_name] __omit_fields__ = [_password] __field_order__ = [user_name, password, groups] password = tw.forms.PasswordField(password, validator=tw.forms.validators.NotEmpty)
  • 19. Userグリッド Sproxclass UserTable(TableBase): __model__ = models.Useruser_table = UserTable(models.DBSession)class UserTableFiller(TableFiller): __model__ = models.Useruser_table_filler = UserTableFiller(models.DBSession)user_table(user_table_filler.get_value())
  • 20. Sprox雑感● AddRecordFormとEditableFormをそれぞれ作らないといけない● SQLAlchemy0.7で動かない!● many-to-manyがうまくフォームに反映されない● デフォルトでアルファベット順になってしまうので、いい感じの順 番にするには、全部指定しなおさないといけません(´・ω・`) 
  • 21. (´・ω・`) そろそろオワコン?
  • 22. Userフォーム FormAlchemyclass UserForm(FieldSet): def __init__(self, **kw): super(UserForm, self).__init__(model=User, **kw) excludes = [self._password] # 追加フィールド self.insert_after(self.user_name, Field(password).password().required()) self.configure(exclude=excludes) # フォーム全体の設定
  • 23. User グリッド FormAlchemyclass UserGrid(Grid): def __init__(self, **kw): super(UserGrid, self).__init__(cls=models.User, **kw) # Edit用のリンク追加 self.append(Field(edit_link, value=lambda u: <a href="%s/edit">Edit</a> % u.id)) self.configure(readonly=True, exclude=[self._password])users = models.DBSession.query(models.User).all()grid = user_grid.bind(users)
  • 24. FormAlchemy雑感やっぱりSQLAlchemy0.7で動かない(´・ω・`) fa.jqueryはまだ安定していないmany-to-manyをしっかりおいかけてくれる開発が活発なので、今後に期待できる
  • 25. 全体的には(・∀・)イイ! と思う
  • 26. Userフォーム tw2.sqlaclass UserForm(tw2.sqla.DbFormPage): entity = models.User class child(tw2.forms.TableForm): user_name = tw2.forms.TextField(validator=tw2.core.Required) password = tw2.forms.PasswordField(validator=tw2.core.Required) user_image = tw2.forms.FileField() groups = tw2.sqla.DbSingleSelectField(entity=models.Group)
  • 27. ● SQLAlchemyのスキーマから自動生成する機能が追加されてき ていますが、使い物になりませんでした。(´・ω・`) ● あと、entityクラスのqueryメソッドを呼ぼうとしたり、Elixirを前提に しすぎです。● 遅延評価できるselectウィジェットに複数選択可能なものがなく、 many-to-manyの関連付けに困ります
  • 28. (゚д゚)マダマダ
  • 29. Userフォーム WTFormsdef group_factory(): return models.DBSession.query(models.Group)class UserForm(wtforms.Form): username = wtforms.TextField(User Name) password = wtforms.PasswordField(Password) groups = QuerySelectMultipleField(query_factory=group_factory )
  • 30. WTForms表示<form method="post"><table>${self.field_row(form.username)}${self.field_row(form.password)}${self.field_row(form.groups)}</table><button type="submit">Add</button></form>
  • 31. WTForms 表示<%def name="field_row(field)"><tr><td>${field.label}</td><td>${field()}</td></tr></%def>
  • 32. WTForms 雑感● やれることが少ない分、はまりどころはなさそうです● でもフォームライブラリ使ってるのにHTMLテーブル書くのはやで す。● B2Cサイトで複雑なHTMLに入れるのに向いてそうですが、そん なことは他のフォームライブラリでできます
  • 33. 機能少なすぎね? (´・ω・`) 
  • 34. Userフォーム deformclass UserSchema(c.MappingSchema): # colanderはSQLAlchemyから自動生成しない user_name = c.SchemaNode(c.String()) password = c.SchemaNode(c.String(), widget=w.PasswordWidget())form = Form(UserSchema(), buttons=(save,))
  • 35. colanderのdeferred bind 定義実行時に、ウィジェット、やバリデータを切り替える仕組み@c.deferreddef group_select_widget(node, kw): groups = kw[groups] return w.SelectWidget(values=[ (g.id, g.group_name) for g in groups ])
  • 36. colander deffered bindingclass Group(c.MappingSchema): # groupを選択するためのスキーマ group_id = c.SchemaNode(c.String(), widget=group_select_widget)class Groups(c.SequenceSchema): # groupを複数選択するためのスキーマ group = Group()class UserSchema(c.MappingSchema): ...... groups = Groups()
  • 37. colanderのdeferred bind バインディングschema = UserSchema()groups = DBSession.query(Group)# バインドschema = schema.bind(groups=groups)form = Form(schema, ....)
  • 38. User フォーム deform バリデーションtry: params = form.validate(controls)except ValidationFailure, e: e.render()
  • 39. deform 雑感● フォームでやりたいことは、おそらくなんでもできます。● シーケンススキーマやマッピングスキーマを組み合わせることで、 複雑な階層を持つスキーマも作成可能。● その分ライブラリの構造が複雑です。
  • 40. (´  > ω < ) むずかしー!
  • 41. ひとまずSQLAlchemyのデータ管理ツールを作るなら、FormAlchemyが一番サポートされている。fa.jqueryは様子見たほうがいい。1リクエストで複数のモデルを扱う場合は、colander / deform がほぼどんな構造でも対応できる。MongoDBなどスキーマレスDBを使う場合は、こちらをおすすめする。
  • 42. スタティックファイルの管理deformやfa.jqueryはjquery.jsやjqueryui.js、その他cssなどが必要フロントのApacheやnginexに任せてしまいたいが、フォームライブラリが使うスタティックファイルはどこにあるのか?ウィジェットライブラリが依存するjsなどをどう管理していくか?
  • 43. Paste deployでがんばr[app:deform_static]use = egg:paste#pkg_resourcesegg = deformresource_name = deform/static[composite:deform]use = egg:paste#urlmap/ = deform_app/static = deform_static[pipeline:deform_demo]pipeline = egg:repoze.tm2#tm deform
  • 44. Fanstatic ● スタティックファイルをホスティングするWSGIアプリ ● スタティックファイルを管理するユーティリティ、ミドルウェア ● fa.jqueryは今後これを使うようになる予定http://pypi.python.org/pypi?%3Aaction=search&term=fanstatic&submit=search
  • 45. Fanstatic 例from fanstatic import Fanstaticfrom js.jqueryui import jqueryui@wsgifydef app(request): jqueryui.need() return Response(body)app = Fanstatic(app)
  • 46. Fanstatic 例body = """<html><head></head><body>Hello</body></html>"""
  • 47. Fanstatic 例 実行結果<html><head> <script type="text/javascript" src="/fanstatic/jquery/jquery.js"></script><script type="text/javascript" src="/fanstatic/jqueryui/ui/jquery-ui.js"></script></head><body>Hello</body></html>
  • 48. 参考● SQLAlchemy http://www.sqlalchemy.org/● ToscaWidgets http://toscawidgets.org/● formencode http://formencode.org/● Sprox http://sprox.org/● tw2 http://toscawidgets.org/documentation/tw2.core/● formalchemy http://docs.formalchemy.org/formalchemy● fa.jquery http://docs.formalchemy.org/fa.jquery/● WTForms http://wtforms.simplecodes.com/● colandar https://docs.pylonsproject.org/projects/colander/dev/● deform https://docs.pylonsproject.org/projects/deform/dev/● fanstatic http://www.fanstatic.org/en/0.11.2/index.html