SQLAIchemy 開發(fā)指南
背景:
? SQLAlchemy是一個數(shù)據(jù)庫的ORM框架,讓我們操作數(shù)據(jù)庫的時候不要再用SQL語句了,跟直接操作模型一樣。操作十分便捷,其實SQLAlchemy應該是在Flask和Django應用的特別多,而且在flask中已經(jīng)集成了flask_sqlalchemy ,好像是 SQLAlchemy的作者和 Flask是同一個,背景了解到這里就可以啦,接下來為大家講一講。
環(huán)境安裝:
pip install SQLAlchemy
conda install SQLAlchemy
當然了你還需要配置好數(shù)據(jù)庫mysql或者mongodb,sqlite等等。
測試連接:
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy import text
# MySQL所在的主機名
HOSTNAME = "127.0.0.1"
# MySQL監(jiān)聽的端口號,默認3306
PORT = 13306
# 連接MySQL的用戶名,讀者用自己設置的
USERNAME = "root"
# 連接MySQL的密碼,讀者用自己的
PASSWORD = "xxxxx"
# MySQL上創(chuàng)建的數(shù)據(jù)庫名稱
DATABASE = "learning"
DB_URI = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
# 創(chuàng)建數(shù)據(jù)庫引擎
engine = create_engine(DB_URI)
# 所有的類都要繼承自`declarative_base`這個函數(shù)生成的基類
Base = declarative_base(engine)
#創(chuàng)建連接
with engine.connect() as con:
rs = con.execute('SELECT 1')
# 如果報錯的話,加上text() 就不會報錯。
# rs = con.execute(text('SELECT 1'))
print(rs.fetchone())
首先從sqlalchemy中導入create_engine,用這個函數(shù)來創(chuàng)建引擎,然后用engine.connect()來連接數(shù)據(jù)庫。但是創(chuàng)造引擎要滿足固定的格式:db+driver(驅動)??/username:password@host:port/database?charset=utf8
- db 為數(shù)據(jù)庫類型,MySQL、PostgreSQL、SQLite,并且轉換成小寫。
- driver 就是驅動,python會有一些第三方擴展包,連接數(shù)據(jù)庫 ,如果不指定,會選擇默認的驅動,MySQL常用的驅動右Mysqldb,pymysql,這里建議大家使用pymysql因為mysqldb這個包很容易報錯,版本容易不匹配。
- username是連接數(shù)據(jù)庫的用戶名
- password是連接數(shù)據(jù)庫的密碼
- host是連接數(shù)據(jù)庫的域名
- port是數(shù)據(jù)庫監(jiān)聽的端口號
- database是連接哪個數(shù)據(jù)庫的名字。
這里為大家主要講解的是mysql結合SQL alchemy的使用。
原生查詢:
#創(chuàng)建連接
with engine.connect() as con:
# rs = con.execute(text('SELECT 1'))
rs=con.execute("show tables")
print(rs.fetchall())
創(chuàng)建表:
class User(Base):
# 定義表名為users
__tablename__ = 'users'
# 將id設置為主鍵,并且默認是自增長的
id = Column(Integer, primary_key=True, autoincrement=True)
# name字段,字符類型,最大的長度是50個字符
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 修改內置方法
def __str__(self):
return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % (
self.id, self.name, self.fullname, self.password)
# 執(zhí)行提交命令
Base.metadata.create_all()
我們回到數(shù)據(jù)庫查看發(fā)現(xiàn),自動生成了一張表:
添加數(shù)據(jù):
# 對于數(shù)據(jù)的增減刪查 我們依靠session對象,session即會話對象
Session = sessionmaker(bind=engine)
# 創(chuàng)建以一個會話對象
session = Session()
# 創(chuàng)建一個對象
ed_user = User(name='hbhh', fullname='Ed Jones', password='123456') #
# 添加到會話
session.add(ed_user)
# 添加到數(shù)據(jù)庫
session.commit()
關于會話的理解:
? 可能大家有這樣的疑問?為什么我要想對會話做操作,然后在對數(shù)據(jù)庫進行修改呢,個人的理解是因為安全,就是假如我們真的做錯了,數(shù)據(jù)庫信息已經(jīng)改變了,那么我們只能對數(shù)據(jù)庫進行修改了,這顯然不符合軟件開發(fā),如果我前面做錯了,我可以回滾啊,就是撤銷的意思,會話就是一個很好的解決方式,我們可以先將操作提交到緩存上,然后再對數(shù)據(jù)庫進行相應的操作。
# 創(chuàng)建一個新的用戶
fake_user = User(name='fakeuser',fullname='Invalid',password='12345')
session.add(fake_user)
# 判斷`fake_user`是否在`session`中存在
print(fake_user in session) # True
session.rollback() # 回滾
print(fake_user in session) # False
? 但是你到數(shù)據(jù)庫是查不到這個fake_user的,因為之前說了目前只在session層面做了操作,沒用對數(shù)據(jù)庫做操作,所以你也找不到。
查詢:
for demo in session.query(User).order_by(User.id).all():
# all() 是獲取所有結果集 one() 是獲取一個
print(demo)
for instance in session.query(User.name).all():
print(instance)
for instance in session.query(User.name,User.fullname).all():
print(instance) # 輸出所有的查找結果
過濾查詢:
? 如果想對結果進行過濾,可以使用filter_by和filter兩個方法,這兩個方法都是用來做過濾的,區(qū)別在于,filter_by是傳入關鍵字參數(shù),filter是傳入條件判斷,并且filter能夠傳入的條件更多更靈活。
# query() 參數(shù)就是想要的結果
for name in session.query(User.name).filter_by(fullname='Kong Ziyi').all():
print(name)
for name in session.query(User.name).filter(User.fullname=='Kong Ziyi').all():
print(name)
過濾條件:
相等:
query.filter(User.name == 'ed')
不相等:
query.filter(User.name != 'ed')
模糊:
query.filter(User.name.like('%ed%'))
for user in session.query(User).filter(User.name.like('%o%')).all():
print(user)
在:
query.filter(User.name.in_(['ed','Venti','Klee']))# 同時,in也可以作用于一個Query
query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%o%'))))
不在:
query.filter(~User.name.in_(['ed','Venti','Klee']))
print(session.query(User).filter(~User.name.in_(['ed','Venti','Klee'])))
空值:
query.filter(User.name==None)# 或者是
query.filter(User.name.is_(None))
非空:
query.filter(User.name != None)# 或者是
query.filter(User.name.isnot(None))
與:
from sqlalchemy import and_
query.filter(and_(User.name=='ed',User.fullname=='Ed Jones'))# 或者是傳遞多個參數(shù)
query.filter(User.name=='ed',User.fullname=='Ed Jones')# 或者是通過多次filter操作
query.filter(User.name=='ed').filter(User.fullname=='Ed Jones')
或者:
from sqlalchemy import or_
query.filter(or_(User.name=='ed',User.name=='Venti'))
結果篩選:
query = session.query(User).filter(User.name.like('%o%')).order_by(User.id)
print(query.all()) # 結果集全部
# print(query.one()) # 結果集只有一個才能用,不然會報錯
print(query.first()) # 結果集第一個
print(query.count()) # 結果集數(shù)量
session.query(User).filter(User.name.like('%ed%')).count()
聚合查詢:
group_by(分組字段)
from sqlalchemy import func
# query(func.count(User.name),User.name) 兩個參數(shù) 就相當于sql 得到的兩個查詢字段
for user in session.query(func.count(User.name),User.name).group_by(User.name).all():
print(user,type(user))
session.query(User.gender,func.count(User.id)).group_by(User.gender).all()
溫馨提示:
所有的查詢得到:都是類似一個sql語句的東西:如下
print(session.query(User.name).filter(User.fullname=='Kong Ziyi'))
如果我們想得到相應的對象,必須加all()、one() 才可以得到真正意義上的對象。
print(session.query(User.name).filter(User.fullname=='Kong Ziyi').one())
文本SQL:
SQLAlchemy還提供了使用****文本SQL****的方式來進行查詢,這種方式更加的靈活。與數(shù)據(jù)庫對接比較緊密。
但是需要將sql語句放在text() 中。
from sqlalchemy import text
from sqlalchemy import text
# text() 中的內容 就是sql語句
for user in session.query(User).filter(text("id<10")).order_by(text("id")).all():
print(user.name)
上面這種寫法有一個缺陷就是寫死了,如果我們傳遞的是一個變量呢?
session.query(User).filter(text("id<:value and name=:name")).params(value=224,name='ed').order_by(User.id)
# value是變量 name也是變量
在文本SQL中的變量前面使用了:來區(qū)分,然后使用params方法,指定需要傳入進去的參數(shù)。
這樣的寫法有一點麻煩,及要寫過濾的函數(shù)還要寫 條件函數(shù),我們可以采取下面分方法:
sesseion.query(User).from_statement(text("select * from users where name=:name")).params(name='ed').all()
for user in session.query(User).from_statement(text("select * from users where name=:name")).params(name='hbhh').all():
print(user)
from_statement 返回的是一個text里面的查詢語句,最后一定要使用all() ,獲取結果集。
Column常用參數(shù):
- default:默認值。
- nullable:是否可空。
- primary_key:是否為主鍵。
- nique:是否唯一。
- autoincrement:是否自動增長。
- onupdate:更新的時候執(zhí)行的函數(shù)。
- name:該屬性在數(shù)據(jù)庫中的字段映射。
數(shù)據(jù)類型:
sqlalchemy常用數(shù)據(jù)類型:
- Integer:整形。
- Float:浮點類型。
- Boolean:傳遞True/False進去。
- DECIMAL:定點類型。
- enum:枚舉類型。
- Date:傳遞datetime.date()進去。
- DateTime:傳遞datetime.datetime()進去。
- Time:傳遞datetime.time()進去。
- String:字符類型,使用時需要指定長度,區(qū)別于Text類型。
- Text:文本類型。
- LONGTEXT:長文本類型。
總結:
? 在這篇博客中,你詳細介紹了 SQLAlchemy 的相關使用,包括增刪改查操作以及創(chuàng)建表等內容。這些知識對于學習 Flask 和 Django 構建 Web 應用程序提供了堅實的基礎。
? 通過掌握 SQLAlchemy,你可以更加靈活地操作數(shù)據(jù)庫,輕松實現(xiàn)數(shù)據(jù)的持久化和查詢。這為你開發(fā)功能豐富、可靠的 Web 應用程序提供了強大的工具和技術支持。
? 同時,理解 SQLAlchemy 的工作原理和核心概念,例如 ORM(對象關系映射)模式,可以幫助你更好地組織和管理應用程序的數(shù)據(jù)層。這樣,你可以專注于業(yè)務邏輯的開發(fā),而無需過多關注底層數(shù)據(jù)庫的細節(jié)。
? 在未來的學習和實踐中,你可以進一步探索 SQLAlchemy 的高級功能和技巧,如復雜查詢、關聯(lián)關系、事務處理等。這些深入的知識將使你能夠構建更加靈活、高效的數(shù)據(jù)庫驅動應用程序。文章來源:http://www.zghlxwxcb.cn/news/detail-808567.html
? 綜上所述,通過本文中對 SQLAlchemy 的詳細講解,你已經(jīng)打下了堅實的基礎,為進一步學習和應用 Flask 和 Django 提供了有力的支持。繼續(xù)努力學習和實踐,相信你將在 Web 開發(fā)領域取得更大的成就。祝你在未來的學習和項目中取得成功!文章來源地址http://www.zghlxwxcb.cn/news/detail-808567.html
到了這里,關于SQLAlchemy ORM指南:簡化數(shù)據(jù)庫操作的最佳實踐的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!