資料庫-SHELL

徐洲更發表於2016-05-12

資料庫按照一定規則儲存程式資料,程式再發起查詢去取回所需的資料。分為文件資料庫(NoSQL)鍵值資料庫(SQL),具體可去百度百科看介紹,這類不再贅述。Web程式最常用是基於關係模型的資料庫

資料庫框架

大多數資料庫引擎都有對應的python包,除此之外還可以選擇資料庫抽象層和SQLAlchemy和MongoEngine。
這裡採用Flask-SQLAlchemy管理資料庫。接下來用的資料是MySQL,安裝方法見[隨筆]
(http://www.jianshu.com/p/9b48ae42e92a)


然而我用的flask搭建python3.5平臺,實際操作過程中出現提示未匯入mysqldb(mysql-python)庫,目前只支援python2.7。所以網站改用python自帶輕量級SQLite。


hello.py:配置資料庫

from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app.config[`SQLALCHEMY_DATABASE_URI`] = `sqlite:///`+os.path.join(basedir,`data.sqlite`)
 #資料庫位置
app.config[`SQLALCHEMY_COMMIT_ON_TEARDOWN`] =True 
#每次請求結束後自動提交資料庫中的變動
db = SQLAlchemy(app)

flask quickstart定義資料位置輸入的是

app.config[`SQLALCHEMY_DATABASE_URI`] = `sqlite:////tmp/test.db`

差異在這裡用basedir獲取該檔案所在路徑,所以資料庫與hello.py同級

hello.py:定義Role和User模型

class NameFome(Form):
    name = StringField(`who are you`, validators=[Required()])
    submit = SubmitField(`Submit`)

class Role(db.Model):
    __tablename__ = `roles` #定義資料庫中使用的表名
    #模型的屬性,定義為db.Column的例項
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(64), unique=True)
    #可選,定義__repr__方法,返回一個具有可讀性的字串表示模型
    def __repr__(self):
        return `<Role %r>` %self.name
        
class User(db.Model):
    __table__name = `users`
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(64),unique=True, index=True)
    
    def __repr__(self):
        return `<User %r>` %self.username

hello.py:關係

class Role(db.Model):
#...
    uers = db.relationship(`User`,backref=`role`)

class User(db.Model):
  #...
    role_id = db.Column(db.Integer,db.ForeignKey(`roles.id`))

所謂關係就是Role和User之間建立了連結。關係用users表中的外來鍵(ForeignKey)連線了兩行。

新增到users表中role_id被定義為外來鍵,傳給db.ForeignKey()的參數列明這列的值是roles表中的id值
新增到Role模型中的users屬性代表這個關係的物件導向視角。db.relationship()第一個參數列明這個關係的另一端是哪個模型。backref引數向User模型中新增一個role屬性,這一屬性可替代role_id訪問Role模型,此時獲取的是模型物件而不是外來鍵的值

上面這段話太複雜了,不懂多看幾遍,下面介紹一下常用的資料庫操作。

預先操作:

python hello.py shell
  1. 建立表
    首先,讓flask-sqlalchemy根據模型類參加資料庫.
    from hello import db
    db.create_all()
  2. insert
    from hello import Role, User
    admin_role = Role(name=`admin`)
    mod_role = Role(name=`moderator`)
    user_role = Role(name=`user`)
    user_john = User(username=`John`,role=admin_role)
    user_susan = User(username=`Susan`,role=mod_role)
    user_david = User(username=`David`,role=user_role)

模型的建構函式(Role())接受的引數(name,username)是使用關鍵字引數指定的模型屬性初始值

通過會話(session)管理資料庫所做的改動。在flask_sqlalchemy中,會話由db.session表示
新增
多個新增

 db.session.add_all([admin_role, mod_role,user_role,user_john,user_susan, user_david])

單個新增

db.session.add(xxx)

提交

db.session.commit()

回滾

db.session.rollback()

始終保證在會話中提交改動,這樣可以避免因部分更新導致資料的不一致性。

3.修改行

admin_role.name = `Administrator`
db.session.add(admin_role)
db.session.commit()

4.刪除行

db.session.delete(mod_role)
db.session.commit()

5.查詢行

Role.query.all()
User.query.filter_by(role=user_role).all()

一旦退出shell會話,這些例子中建立的物件不會以python物件的形式存在,而是作為各自資料庫中的行。重新開啟shell會話,需要從資料庫中讀取行,再重新建立python物件。
如果每次啟動shell會話都要匯入資料庫例項和模型,那麼真的要難過死了。這個可以通過為shell增加一個上下文解決

from flask.ext.script import Manager, Shell
def make_shell_context():
    return dict(app=app,db=db,User=User,Role=Role)
manager.add_command("shell",Shell(make_context=make_shell_context))


相關文章