フォーム処理
次の変更は、インタラクティブシェルの代わりにアプリケーション内でユーザとリストを管理するフォームです。
最初に、ユーザ削除と追加を加えます。両方の動作はユーザのユニークなe-mailアドレスを必要とするでしょう。
実行の動作はステータスメッセージをディスプレイへ表示させ、/users/indexへリダイレクトさせます。
これらのメソッドはPOSTリクエストの結果からです。そしてクライアントを直ぐにリダイレクトします。
新しいテンプレートは必要ないです。ここでは新しい2つのメソッドをUsersコントローラに追加します。
class Users: ... @turbogears.expose() def add(self, email): # Remove extra spaces email = email.strip() # Remove null bytes (they can seriously screw up the database) email = email.replace('\x00', '') if email: try: user = model.User.byEmail(email) except model.SQLObjectNotFound: user = model.User(email=email) turbogears.flash("User %s added!" % email) else: turbogears.flash("User %s already exists!" % email) else: turbogears.flash("E-mail must be non-empty!") raise cherrypy.HTTPRedirect('index') @turbogears.expose() def remove(self, email): try: user = model.User.byEmail(email) except model.SQLObjectNotFound: turbogears.flash("The user %s does not exist. (Did someone else remove it?)" % email) else: for l in user.lists: for item in l.items: item.destroySelf() l.destroySelf() user.destroySelf() turbogears.flash("User %s removed!" % email) raise cherrypy.HTTPRedirect('index')
メソッドを追加のための注意。ここでは入力されたemailが空ではなく正しく作られたかを非常に簡単に検証した。
現実では、ここには正規表現を使う。ユーザの重複登録や存在しないユーザの変更の安全のために、すべてtry/exceptブロックします。
いくつか検証は一般のWebサービスには必要です。
ここで、フォームに複数のメソッドを加えます。actionはUsersコントローラに加えた対応するメソッドの名前です。
tutorial/templates/users.kidの
<form action="add" method="POST"> <fieldset> <legend>Add a User</legend> <label for="email">Email:</label> <input type="text" name="email"/> <input type="submit" value="Add"/> </fieldset> </form>
次に、リストユーザの削除ボタンを加えます。リストアイテムにボタンを加えるために、users.kidの中のリストを変更します。
<ol> <li py:for="user in users"> <form style="float: right" action="remove" method="POST"> <input type="hidden" name="email" value="${user.email}"/> <input type="submit" value="Remove"/> </form> <span>${user.email} (<a href="${user.id}">View lists</a>)</span> </li> </ol>
Usersページを再読込して、ユーザの追加と削除を試します。turbogears.flashで呼ばれたステータスメッセージが結果として表示されます。
この処理はフォームへのリストとアイテムの修正に似ている。したがって、多くの説明しません。代わりに次のコードを見ください。
これは新しいtutorial/templates/user.kidの
です。<h2>${user.email}'s Lists</h2> <div py:for="userList in user.lists"> <form style="float: right" action="/removeList" method="POST"> <input type="hidden" name="userID" value="${user.id}"/> <input type="hidden" name="listID" value="${userList.id}"/> <input type="submit" value="Delete This List"/> </form> <h3>${userList.title} </h3> <ol> <li py:for="item in userList.items"> <form style="float: right" action="/removeItem" method="POST"> <input type="hidden" name="userID" value="${user.id}"/> <input type="hidden" name="itemID" value="${item.id}"/> <input type="submit" value="Remove"/> </form> <span>${item.value}</span> </li> </ol> <form action="/addItem" method="POST"> <input type="hidden" name="userID" value="${user.id}"/> <input type="hidden" id="listID" name="listID" value="${userList.id}"/> <label>Add Item: <input type="text" name="value"/></label> <input type="submit" value="Add"/> </form> </div> <form action="/addList" method="POST"> <fieldset> <legend>Create a List</legend> <input type="hidden" name="userID" value="${user.id}"/> <label for="title">Title:</label> <input type="text" id="title" name="title"/> <input type="submit" value="Create"/> </fieldset> </form>
個人的メモ7
from turbogears import controllers, expose, flashとしてやると、turbogearsをいれなくてもそれぞれ呼び出せる。
from model import * で modelがなくなる
ルートコントローラーを加えます。
class Root(controllers.RootController): ... @turbogears.expose() def addList(self, userID, title): try: userID = int(userID) user = model.User.get(userID) except (ValueError, model.SQLObjectNotFound): raise cherrypy.NotFound else: # Remove extra spaces title = title.strip() # Remove null bytes (they can seriously screw up the database) title = title.replace('\x00', '') if title: l = model.List(title=title, user=user) turbogears.flash("List created!") else: turbogears.flash("Title must be non-empty!") raise cherrypy.HTTPRedirect('/users/%s' % userID) @turbogears.expose() def removeList(self, userID, listID): try: listID = int(listID) l = model.List.get(listID) except ValueError: turbogears.flash("Invalid list!") except model.SQLObjectNotFound: turbogears.flash("List not found! (Did someone else remove it?)") else: for item in l.items: item.destroySelf() l.destroySelf() turbogears.flash("List deleted!") raise cherrypy.HTTPRedirect('/users/%s' % userID) @turbogears.expose() def addItem(self, userID, listID, value): try: listID = int(listID) l = model.List.get(listID) except ValueError: turbogears.flash("Invalid list!") except model.SQLObjectNotFound: turbogears.flash("List not found! (Did someone else remove it?)") else: # Remove extra spaces value = value.strip() # Remove null bytes (they can seriously screw up the database) value = value.replace('\x00', '') if value: item = model.Item(listID=listID, value=value) turbogears.flash("Item added!") else: turbogears.flash("Item must be non-empty!") raise cherrypy.HTTPRedirect('/users/%s' % userID) @turbogears.expose() def removeItem(self, userID, itemID): try: itemID = int(itemID) item = model.Item.get(itemID) except ValueError: turbogears.flash("Invalid item!") except model.SQLObjectNotFound: turbogears.flash("No such item! (Did someone else remove it?)") else: item.destroySelf() turbogears.flash("Item removed!") raise cherrypy.HTTPRedirect('/users/%s' % userID)