Tornado からの SQLAlchemy です。
Tornado を使った実装から。
ui_main.py
from sqlalchemy.orm import sessionmaker import tornado.ioloop from tornado.web import * from db_construct import engine from dw_define import * import tr_uw2dw import tr_dw2uw Session = sessionmaker(bind=engine) class MainHandler(RequestHandler): def get(self): self.render("main.html") class PersonHandler(RequestHandler): def get(self): session = Session() person_list = tr_dw2uw.person_list( session.query(Person).order_by(Person.id)) session.close() self.render("person.html", person_list=person_list) def post(self): session = Session() session.add(tr_uw2dw.person(self.get_argument("name"))) session.commit() person_list = tr_dw2uw.person_list( session.query(Person).order_by(Person.id)) session.close() self.render("person.html", person_list=person_list) application = Application([ (r"/", MainHandler), (r"/person", PersonHandler) ]) if __name__ == "__main__": map_to_db() application.listen(8888) tornado.ioloop.IOLoop.instance().start()
http://localhost:8888/person にアクセスすると、person.html が表示されます。で、その person.html。
<html> <head> <title>Person Management</title> </head> <body> <div> <a href="/">Main</a> > Person Management </div> <form action="/person" method="post"> Name : <input type="text" name="name"> <input type="submit" value="Add"> </form> <table> <tr><th>ID</th><th>Name</th></tr> {% for i in person_list %} <tr><td>{{ i.id }}</td><td>{{ i.name }}</td></tr> {% end %} </table> </body> </html>
person.html はテンプレートです。render メソッドで指定したパラメータ person_list を使っています。で、person_list に渡しているオブジェクトを作っているのが、tr_dw2hw.py。
import collections from dw_define import * def person_list(persons): PersonT = collections.namedtuple("PersonT", "id name") return [PersonT(p.id, p.name) for p in persons]
dict を使おうかとも思ったけど、参照する側(person.html)の記述量が増えるので名前付きタプルにした。変換せずに渡すという手もあるけど。ちょっと関数型チックな記述の仕方をしてみました。
今度は、person.html から Submit したときに呼ばれる post メソッド。tr_hw2dw.py で変換しています。
from dw_define import * def person(name): person = Person(name) person.customer = Customer() return person
渡されたパラメータから、DBに格納するためにオブジェクトを構築しています。post メソッドの実装では、そのオブジェクトを session に add しています。
最後に残った謎の dw_define.py。
from sqlalchemy import * from sqlalchemy.orm import mapper from sqlalchemy.orm import relation from db_construct import engine class Person: def __init__(self, name): self.name = name class Company: def __init__(self, name): self.name = name class Customer: pass class PersonCustomer: pass class CompanyCustomer: pass def map_to_db(): metadata = MetaData() metadata.reflect(bind=engine, views=True) mapper(Person, metadata.tables['person'], properties={ 'customer': relation(Customer, uselist=False, backref='person') }) mapper(Company, metadata.tables['company'], properties={ 'customer': relation(Customer, uselist=False, backref='company') }) mapper(Customer, metadata.tables['customer']) mapper(PersonCustomer, metadata.tables['person_customer'], primary_key=[metadata.tables['person_customer'].get_children()[0]]) mapper(CompanyCustomer, metadata.tables['company_customer'], primary_key=[metadata.tables['company_customer'].get_children()[0]]) return metadata
クラス定義とDBとのマッピングです。
Tornado と SQLAlchemy の使い方の参考にはしても、設計は真似ちゃダメですよ。いい設計とは言えませんので。