python框架之Flask基礎篇(二)-------- 數據庫的操做

1.flask鏈接數據庫的四步:

  1. 倒入第三方數據庫擴展包:from flask_sqlalchemy import SQLAlchemy
  2. 配置config屬性,鏈接數據庫:

    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = Falsepython

  3. 建立數據庫first_flask
  4. 建立操做數據庫對象:db = SQLAlchemy(app)

下面直接上代碼解釋:mysql

 

# -*- coding:utf-8 -*-
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # url的格式爲:數據庫的協議://用戶名:密碼@ip地址:端口號(默承認以不寫)/數據庫名
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask" # 動態追蹤數據庫的修改. 性能很差. 且將來版本中會移除. 目前只是爲了解決控制檯的提示才寫的 app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False # 建立數據庫的操做對象 db = SQLAlchemy(app) class Role(db.Model): __tablename__ = "roles" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(16),unique=True) # 給Role類建立一個uses屬性,關聯users表。 # backref是反向的給User類建立一個role屬性,關聯roles表。這是flask特殊的屬性。 users = db.relationship('User',backref="role") # 至關於__str__方法。 def __repr__(self): return "Role: %s %s" % (self.id,self.name) class User(db.Model): # 給表從新定義一個名稱,默認名稱是類名的小寫,好比該類默認的表名是user。 __tablename__ = "users" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(16),unique=True) email = db.Column(db.String(32),unique=True) password = db.Column(db.String(16)) # 建立一個外鍵,和django不同。flask須要指定具體的字段建立外鍵,不能根據類名建立外鍵 role_id = db.Column(db.Integer,db.ForeignKey("roles.id")) def __repr__(self): return "User: %s %s %s %s" % (self.id,self.name,self.password,self.role_id) @app.route('/') def hello_world(): return 'Hello World!'


if __name__ == '__main__': # 刪除全部的表 db.drop_all() # 建立表 db.create_all() ro1 = Role(name = "admin") # 先將ro1對象添加到會話中,能夠回滾。 db.session.add(ro1) ro2 = Role() ro2.name = 'user' db.session.add(ro2) # 最後插入完數據必定要提交 db.session.commit() us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id) us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id) us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id) us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id) us5 = User(name='tang', email='tang@itheima.com', password='158104', role_id=ro2.id) us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id) us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id) us8 = User(name='liu', email='liu@itheima.com', password='867322', role_id=ro1.id) us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id) us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id) db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10]) db.session.commit() app.run(debug=True)

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------sql

下面插播一條bug:數據庫

當把表格建立完成,註釋這兩句話:django

 # 刪除全部的表 db.drop_all() # 建立表 db.create_all()

而後向表格裏面插入數據,此時會出現這樣的錯誤:flask

sqlalchemy.exc.IntegrityError: (_mysql_exceptions.IntegrityError) (1062, "Duplicate entry 'admin' for key 'name'") [SQL: u'INSERT INTO roles (name) VALUES (%s)'] [parameters: ('admin',)]session

查了網上的好多資料說把字段的約束unique=True去掉就行了,可是根本緣由不在這。app

緣由就是由於app.run(debug=True)。開啓debug模式以後,當咱們修改代碼的時候,好比將刪除表和建立表這兩句話註釋,而後打開插入數據的註釋。這個過程debug模式默認就已經把程序運行一遍了。此時數據庫就已經有了數據,當咱們再次手動執行的時候,又往數據庫中插入了一條數據,這時候就會報錯。由於字段的約束是惟一性的unique,因此解決的辦法有兩種:框架

第一種:就是不要將刪除表和建立表這兩句話註釋,每次執行都要帶着這兩個句話。不管是debug模式自動執行仍是咱們手動執行程序,都會先刪除表而後再建立表,因此執行多少次都不怕。函數

第二種:關閉debug模式。就是這樣app.run()

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.數據庫的增刪改查:

1.如下的方法都是返回一個新的查詢,須要配合執行器使用。

filter(): 過濾,功能比較強大。
filter_by():過濾,用在一些比較簡單的過濾場景。

order_by():排序。默認是升序,降序須要導包:from sqlalchemy import * 。而後引入desc方法。好比order_by(desc("email")).按照郵箱字母的降序排序。

 

group_by():分組。

2.如下都是一些經常使用的執行器:配合上面的過濾器使用。

get():得到id等於幾的函數。好比:查詢id=1的對象。get(1)。切記:括號裏沒有「id=」,直接傳入id的數值就ok。由於該函數的功能就是查詢主鍵等於幾的對象。

all():查詢全部的數據。

first():查詢第一個數據。

count():返回查詢結果的數量。

paginate():分頁查詢,返回一個分頁對象。paginate(參數1,參數2,參數3)

參數1:當前是第幾頁,參數2:每頁顯示幾條記錄,參數3:是否要返回錯誤。

返回的分頁對象有三個屬性:items:得到查詢的結果,pages:得到一共有多少頁,page:得到當前頁。

3.經常使用的邏輯符:

須要倒入包才能用的有:from sqlalchemy import * 

not_  and_  or_   還有上面說的排序desc。

經常使用的內置的有:in_      表示某個字段在什麼範圍之中。

4.其餘關係的一些數據庫查詢:

endswith():以什麼結尾。

startswith():以什麼開頭。

contains():包含

5.下面體會一下上面的這些用法:

1. 查詢全部用戶數據 User.query.all() 2. 查詢有多少個用戶 User.query.count() 3. 查詢第1個用戶 User.query.first() 4. 查詢id爲4的用戶[3種方式] User.query.get(4) User.query.filter_by(id=4).first()     User.query.filter(User.id==4).first() filter:(類名.屬性名==) filter_by:(屬性名=) filter_by: 用於查詢簡單的列名,不支持比較運算符 filter比filter_by的功能更強大,支持比較運算符,支持or_、in_等語法。 5. 查詢名字結尾字符爲g的全部數據[開始/包含] User.query.filter(User.name.endswith('g')).all() User.query.filter(User.name.contains('g')).all() 6. 查詢名字不等於wang的全部數據[2種方式] from sqlalchemy import not_
注意了啊:邏輯查詢的格式邏輯符_(類屬性其餘的一些判斷) User.query.filter(not_(User.name
=='wang')).all() User.query.filter(User.name!='wang').all() 7. 查詢名字和郵箱都以 li 開頭的全部數據[2種方式] from sqlalchemy import and_ User.query.filter(and_(User.name.startswith('li'), User.email.startswith('li'))).all() User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all() 8. 查詢password是 `123456` 或者 `email` 以 `itheima.com` 結尾的全部數據 from sqlalchemy import or_ User.query.filter(or_(User.password=='123456', User.email.endswith('itheima.com'))).all() 9. 查詢id爲 [1, 3, 5, 7, 9] 的用戶列表 User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all() 10. 查詢name爲liu的角色數據 關係引用 User.query.filter_by(name='liu').first().role.name 11. 查詢全部用戶數據,並以郵箱排序 排序 User.query.order_by('email').all() 默認升序 User.query.order_by(desc('email')).all() 降序 12. 查詢第2頁的數據, 每頁只顯示3條數據 help(User.query.paginate) 三個參數: 1. 當前要查詢的頁數 2. 每頁的數量 3. 是否要返回錯誤 pages = User.query.paginate(2, 3, False) pages.items # 獲取查詢的結果 pages.pages # 總頁數 pages.page # 當前頁數

 3.使用第三方擴展框架遷移數據庫文件。

使用框架須要配置的代碼以下:

# -*- coding:utf-8 -*-
from flask import Flask from flask_sqlalchemy import SQLAlchemy # 操做數據庫的擴展包 from flask_script import Manager # 用命令操做的擴展包 from flask_migrate import Migrate,MigrateCommand # 操做數據庫遷移文件的擴展包 app = Flask(__name__) app.debug = True app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/second_flask" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db = SQLAlchemy(app) manager = Manager(app) # 建立遷移對象 migrate = Migrate(app,db) # 將遷移文件的命令添加到‘db’中 manager.add_command('db',MigrateCommand) class Role(db.Model): __tablename__ = "table_roles" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(16),unique=True) info = db.Column(db.String(100)) Users = db.relationship("User",backref='role') class User(db.Model): __tablename__ = "table_users" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(16),unique=True) info = db.Column(db.String(200)) role_id = db.Column(db.Integer,db.ForeignKey("table_roles.id")) @app.route('/') def hello_world(): return 'Hello World!'


if __name__ == '__main__': manager.run()

 

使用遷移命令以下:

好比上面的代碼所在的文件名稱爲database.py。

1.python database.py db init    生成管理遷移文件的migrations目錄

2.python database.py db migrate -m "註釋"   在migrations/versions中生成一個文件,該文件記錄數據表的建立和更新的不一樣版本的代碼。

3.python database.py db upgrade  在數據庫中生成對應的表格。

4.當須要改表格的時候,改完先執行第二步,而後再執行第三步。

5.須要修改數據表的版本號的時候須要作的操做以下:

python database.py db upgrade 版本號  向上修改版本號

python database.py db downgrade 版本號   向下修改版本號

可能用到的其餘的語句:

python database.py db history    查看歷史版本號

python database.py db current   查看當前版本號

相關文章
相關標籤/搜索