web.py開發web 第四章 Sqlalchemy(事件監聽與初始化)

    上一章講了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表後插入了超級管理員的數據,並對密碼進行加密了:)
相關文章
相關標籤/搜索