標籤:網上 model 引入 使用者 根據 prim 增刪改 sql contain
1.flask串連資料庫的四步:
- 倒入第三方資料庫擴充包:from flask_sqlalchemy import SQLAlchemy
- 配置config屬性,串連資料庫:
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:[email protected]/first_flask"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
- 建立資料庫first_flask
- 建立操作資料庫對象:db = SQLAlchemy(app)
下面直接上代碼解釋:
# -*- coding:utf-8 -*-from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# url的格式為:資料庫的協議://使用者名稱:密碼@ip地址:連接埠號碼(預設可以不寫)/資料庫名app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:[email protected]/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=‘[email protected]‘, password=‘123456‘, role_id=ro1.id) us2 = User(name=‘zhang‘, email=‘[email protected]‘, password=‘201512‘, role_id=ro2.id) us3 = User(name=‘chen‘, email=‘[email protected]‘, password=‘987654‘, role_id=ro2.id) us4 = User(name=‘zhou‘, email=‘[email protected]‘, password=‘456789‘, role_id=ro1.id) us5 = User(name=‘tang‘, email=‘[email protected]‘, password=‘158104‘, role_id=ro2.id) us6 = User(name=‘wu‘, email=‘[email protected]‘, password=‘5623514‘, role_id=ro2.id) us7 = User(name=‘qian‘, email=‘[email protected]‘, password=‘1543567‘, role_id=ro1.id) us8 = User(name=‘liu‘, email=‘[email protected]‘, password=‘867322‘, role_id=ro1.id) us9 = User(name=‘li‘, email=‘[email protected]‘, password=‘4526342‘, role_id=ro2.id) us10 = User(name=‘sun‘, email=‘[email protected]‘, 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)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面插播一條bug:
當把表格建立完成,注釋這兩句話:
# 刪除所有的表 db.drop_all() # 建立表 db.create_all()
然後向表格裡面插入資料,此時會出現這樣的錯誤:
sqlalchemy.exc.IntegrityError: (_mysql_exceptions.IntegrityError) (1062, "Duplicate entry ‘admin‘ for key ‘name‘") [SQL: u‘INSERT INTO roles (name) VALUES (%s)‘] [parameters: (‘admin‘,)]
查了網上的好多資料說把欄位的約束unique=True去掉就好了,但是根本原因不在這。
原因就是因為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.name11. 查詢所有使用者資料,並以郵箱排序排序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 # 當前頁數
python架構之Flask基礎篇(二)-------- 資料庫的操作