在sqlalchemy.schema和sqlalchemy.types這兩個module中,包含了定義數據庫schema所需要的所有類,如Table、Column、String、Text、Date、Time、Boolean等。還是來看一個例子:
?1?from?sqlalchemy.engine?import?create_engine
?2?from?sqlalchemy.schema?import?MetaData,?Table,?Column,?ForeignKey,?Sequence
?3?from?sqlalchemy.types?import?*
?4?
?5?engine?=?create_engine('postgres://test:test@localhost/test',?echo=True)
?6?
?7?metadata?=?MetaData()
?8?metadata.bind?=?engine
?9?
10?book_table?=?Table('book',?metadata,
11?????Column('id',?Integer,?Sequence('seq_pk'),?primary_key=True),
12?????Column('title',?Unicode(255),?nullable=False),
13?)
14?
15?author_table?=?Table('author',?metadata,
16?????Column('id',?Integer,?Sequence('seq_pk'),?primary_key=True),
17?????Column('name',?Unicode(255),?nullable=False),
18?)
19?
20?bookauthor_table?=?Table('bookauthor',?metadata,
21??? Column('book_id',?Integer,?ForeignKey('book.id'),?nullable=False),
22??? Column('author_id',?Integer,?ForeignKey('author.id'),?nullable=False),
23)
24
25metadata.create_all(checkfirst=True)
首先我們還是create_engine,然后新建一個MetaData對象,把engine綁上去,接下來,開始在metadata中定義表結構(metadata由Table構造函數傳入),我們這里定義了3張表,分別是book、author和bookauthor關系表(“多對多”),其中新建一個Sequence對象,專門處理主鍵生成。最后我們通過執行metadata.create_all()創建數據庫表,參數checkfirst=True表示如果數據庫相關對象已經存在,則不重復執行創建。
對于已經存在于數據庫中的表,我們可以通過傳入autoload=True參數到Table構造函數的方式來加載現有的表結構到metadata中,而不必挨個兒再寫一遍Column清單。
看到這兒,你也許覺得挺麻煩,不是么?Django和RoR都是可以直接定義數據model類,順帶就把schema也定義了,而不是像這樣單獨去寫表結構的schema,顯得很"底層"。確實,這樣用SQLAlchemy并不是最優化的,SQLAlchemy本身并不會自動的幫你做很多事,但它基礎打得很牢。如果你感興趣,也可以先去看一下SQLAlchemy的擴展模塊Elixir,通過Elixir,你可以像Ruby on Rails那樣定義出實體和關系("Active Record")。
在稍后的第4部分中,我們會去了解如何以聲明方式來更緊湊的定義我們的model/schema(0.5新特性)。鑒于筆者傾向于更強的控制力,所以在這個系列中就不去介紹SQLAlchemy的其他擴展模塊了,如Elixir、SQLSoup等,大家可以根據需要去找下官方文檔。