在學tornado的時候涉及以下資料庫操作,現在暫時使用mysql資料庫,所以選擇了一個比較好用的ORM工具sqlalchemy,順便記一下使用過程
安裝
首先安裝mysql
pip安裝必要的庫:pip install sqlalchemy
下載mysql-python驅動:
http://www.codegood.com/archives/129
如果是32位版本的windows選win32,如果是64的可以選擇amd64
配置
首先需要一個資料庫配置檔案
# -*- coding: utf-8 -*-
DB_HOST = `127.0.0.1`
# DB_HOST = `127.0.0.1`
DB_USER = `root`
# DB_USER = `root`
DB_PWD = ``
# DB_PWD = `084358`
DB_NAME = `my404`
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() #create Base lei
engine = create_engine(`mysql://%s:%s@%s/%s?charset=utf8` %
(DB_USER, DB_PWD, DB_HOST, DB_NAME),
encoding=`utf-8`, echo=False,
pool_size=100, pool_recycle=10)
這裡我寫了一個db.py檔案,目錄在tornado專案根目錄下的mod.databases下
接下來是一段類似於orm裡實體類部分的程式碼,我同樣放在了mod.databases下,名字為tables.py
from sqlalchemy import Column, String, Integer, VARCHAR,ForeignKey, Float
from sqlalchemy.orm import relationship,backref
from db import engine,Base
class Article(Base):
__tablename__ = `articles`
user = Column(VARCHAR(20),primary_key = True)
title = Column(VARCHAR(40))
time = Column(VARCHAR(20))
content = Column(VARCHAR(2000))
每個類對應一個表,上方匯入必要的庫和db裡的一些配置資訊,注意一定要設定一項為primary_key,不然在查詢時會報錯Could not assemble any primary key columns for mapped table
這就是大概需要配置的部分,如果需要用新的表就在tables.py裡面加入新的類就好了
使用
如下,在自己的main.py裡需要對定義的application裡面做一下資料庫的設定,通過self.db修改屬性來設定一些和資料庫相關的操作。但是具體其中的屬性還不太瞭解,就先放著了。
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", IndexHandler),
]
settings = dict(
debug=True,
static_path=os.path.join(os.path.dirname(__file__),"static"),
template_path=os.path.join(os.path.dirname(__file__), "templates")
)
tornado.web.Application.__init__(self, handlers, **settings)
self.db = scoped_session(sessionmaker(bind=engine,
autocommit=False, autoflush=True,
expire_on_commit=False))
if __name__ == `__main__`:
tornado.options.parse_command_line()
Application().listen(options.port, address=`127.0.0.1`)
tornado.ioloop.IOLoop.instance().start()
在具體的handler裡使用時如下
from tornado.httpclient import HTTPRequest, AsyncHTTPClient
from mod.databases.tables import Article
import tornado.web
import tornado.gen
import urllib
class DbHandler(tornado.web.RequestHandler):
@property
def db(self):
return self.application.db
def get(self):
data = self.db.query(Article).all()
for item in data:
print item.content
一方面對使用的實體類要進行匯入,如
from mod.databases.tables import Article
另一方面db函式上方
@property
標註是python關於屬性的標註,有了這個標註就可以使用self.db來直接獲取連線物件,而不需要加上括號self.db(),看起來會比較直觀
查詢
具體的查詢語句就是
data = self.db.query(Article).all()
這裡我從資料庫裡取出資料後只把每一項的content列輸出了,並沒有進行其他操作。
其他的使用方法可以參考sqlalchemy的官方文件
http://docs.sqlalchemy.org/en/rel_1_0/or…
插入
new_user = User(user_email = email,user_name = name,user_psd = psd)
self.db.add(new_user)
self.db.commit()
self.db.close()#用完後關閉資料庫連線,否則可能 導致此次連線時間過長而未操作,資料庫連線超時的問題
需要注意的地方是commit函式,如果沒有commit,那麼self.db裡還是儲存著之前的資訊,這樣說似乎不太明白,但是我在使用的過程中發生了一個這樣的情景:
我搭建了一個小網站,可以用於註冊登入,在我註冊時我先檢測相關資訊是否合法,例如使用者名稱(郵箱)是否已存在:
user = self.db.query(User).filter(User.user_email == self.email).first()
if user!=None:
表示使用者名稱已存在
返回錯誤資訊
else:
使用者名稱不存在,可以註冊
new_user = User(user_email = email,user_name = name,user_psd = psd)
self.db.add(new_user)
self.db.commit()
但緊接著,我又做了一件沒有什麼必要做的事情(請不要吐槽,我只是這麼寫了一下,其實目的是檢測一下這個使用者是否在資料庫中存在了,然後返回註冊成功的資訊
user = self.db.query(User).filter(User.user_name == name).first()
if(user.user_email == email):
self.db.commit()
data["status"] = 200
data["data"] = "Register Success"
標記2
self.write(data)
但是這麼做令我出現了一個麻煩
在我註冊成功後,我從資料庫中緊接著刪除了這個使用者,然後重新註冊,這時候他顯示這個使用者還是存在的…
在我將tornado的服務重啟後,用同樣的使用者名稱去註冊,發現這時候又不顯示該使用者存在了,於是註冊成功
之後我在標記2處加了一句self.db.commit()後這個問題就不再出現了。
一般我們還會採取的操作是
原因是因為self.db其實是sqlalchemy的scoped_session,他相當於未commit時有個快取,查詢結果也會快取在其中。於是雖然資料庫裡刪除了某使用者,但是在刪除之前我做了一次對這個使用者的查詢,導致self.db裡快取了這個使用者。所以下次他直接在快取裡找到了這個使用者。
重啟服務後快取清掉了,也就恢復正常和資料庫保持同步了…
具體的原因還得看看文件…如果有知道的同學歡迎指導啊=.=