上一章講了sqlalchemy的數據庫建立,我想你們應該會慢慢喜歡上用這種方式來建立數據庫吧,sqlalchemy不單單能自動建立數據庫,更提供了其餘更強大的功能,今天要介紹的就是sqlalchemy中的事件監聽,並將其應用到數據庫的初始化中。 python
上一章的數據庫建立,除了將user表建立出來,咱們並無進行其餘的操做,而每每咱們的web開發,總須要在網站中設計一個超級管理員,這個超級管理員不是註冊出來的,而是在數據庫建立初期就有的,那麼,咱們能夠在models.py中建立user表,並同時向user表插入超級管理員的信息,而在插入超級管理員或者之後的修改密碼、新增用戶的時候,咱們的密碼都是須要加密的,那麼這時就能夠添加一個事件觸發,當插入設置password字段時,自動加密,好,需求有了,接下來就是行動了,咱們把原來的models.py修改爲如下代碼:
models.py mysql
# -*- coding:utf-8 -*- from sqlalchemy import * from sqlalchemy import event from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker import hashlib #這裏定義一個password加密混淆 password_prefix = "Ad%cvcsadefr^!deaf" #定義數據庫的帳號、端口、密碼、數據庫名,使用的鏈接模塊,這裏用的是mysqldb engine = create_engine( 'mysql+mysqldb://root:1234567@localhost:3306/tech?charset=utf8', echo=False#是否輸出數據庫操做過程,很方便調試 ) #定義一個函數,用來獲取sqlalchemy的session def bindSQL(): return scoped_session(sessionmaker(bind=engine)) Base = declarative_base() Base.__table_args__ = {'mysql_engine':'InnoDB'}#定義數據表使用InnoDB class User(Base): __tablename__ = "user" id = Column(Integer, primary_key=True) name = Column(String(20), unique=True) email = Column(String(32), unique=True) password = Column(String(32)) superuser = Column(Boolean, default=False) metadata = Base.metadata #定義一個回調函數用於響應觸發事件 def setPassword(target, value, oldvalue, initiator): if value == oldvalue:#若是新設置的值與原有的值相等,那麼說明用戶並無修改密碼,返回原先的值 return oldvalue #若是新值與舊值不一樣,說明密碼發生改變,進行加密,加密方法能夠根據本身需求改變 return hashlib.md5("%s%s" % (password_prefix, value)).hexdigest() #設置事件監聽,event.listen(表單或表單字段, 觸發事件, 回調函數, 是否改變插入值) event.listen(User.password, "set", setPassword, retval=True) #爲了不重複插入數據,定義一個get_or_create函數,這個是模仿django的,有興趣的同窗能夠google下 def get_or_create(session, model, **kwargs): if "defaults" in kwargs: defaults = kwargs["defaults"] del kwargs["defaults"] else: defaults = {} instance = session.query(model).filter_by(**kwargs).first() if instance: return instance, False else: kwargs.update(defaults) instance = model(**kwargs) session.add(instance) session.flush() session.refresh(instance) return instance, True #定義初始化函數 def initModel(): metadata.create_all(engine)#建立數據庫 db = bindSQL()#獲取sqlalchemy的session #建立超級管理員,這裏爲了不屢次運行initModel而發生重複插入的狀況,使用了get_or_create方法 obj, created = get_or_create( db, User, name="administrator", defaults={ "email": "332535694@qq.com", "password": "administrator", "superuser": True } ) db.commit()#記得commit喔,否則數據最後仍是沒插入 db.remove() if __name__ == "__main__": initModel()將上一章建立的user表刪除,運行下python models.py,看看是否是建立user表後插入了超級管理員的數據,並對密碼進行加密了:)