Python中使用sqlalchemy插件能夠實現ORM(Object Relationship Mapping,模型關係映射)框架,而Flask中的flask-sqlalchemy其實就是在sqlalchemy外進行了一層封裝,使得在flask中使用起來更加方便,固然sqlalchemy的原有的方法也均可以使用。也就是說sqlalchemy在普通的Python程序中也可使用,而flask-sqlalchemy是爲flask「定製」的。python
我這裏使用的是MySQL數據庫,Python3中對應的驅動插件爲pymysql(Python2中對應的驅動插件爲mysql-python),因此這裏的數據庫操做須要安裝MySQL、pymysql(或mysql-python)和flask-sqlalchemy。mysql
1、MySQL數據庫安裝(其實MySQL的東西網上一大推)sql
安裝版:exe安裝版按照步驟一步步來就好了,能夠只安裝MySQL服務便可,若是電腦上沒有對應版本VS C++也會提示你安裝的。數據庫
免安裝版/解壓版:根據如下步驟進行便可:flask
[mysqld]
basedir=D:\MySQL Server 8.0
datadir=D:\MySQL Server 8.0\datasession
注:解壓後能夠本身更改文件夾名稱,好比我這兒是「MySQL Server 8.0」,配置這兩個信息後,其中的「data」文件夾不要本身建立(默認是沒有這個文件夾的,可是會在下一步自動建立),不然MySQL服務會啓動失敗。app
安裝和使用過程當中遇到的問題和解決方案:框架
2、數據庫驅動插件安裝(pymysql/mysql-python)ide
3、SQLAlchemy使用函數
1.安裝:pip install sqlalchemy
2.鏈接數據庫:設置數據庫鏈接字符串,並使用create_engine函數建立一個engine對象,並使用engine對象的connect方法鏈接數據庫,注意鏈接數據庫後須要使用close方法關閉鏈接。
from sqlalchemy import create_engine # 數據庫鏈接信息 HOSTNAME = '127.0.0.1' # 本機地址 PORT = '3306' # MySQL默認端口 DATABASE = 'sqlalchemy_demo' # 數據庫名 USERNAME = 'root' # 安裝數據庫時設置的用戶名和密碼 PASSWORD = '123456' # 數據庫鏈接字符串 # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) # 建立一個engine對象 engine = create_engine(DB_URI) # 鏈接數據庫 conn = engine.connect() # 執行SQL語句,並返回執行結果 sel_res = conn.execute('select * from User') # 獲取並打印一條查詢結果 print(sel_res.fetchone()) # 關閉鏈接 conn.close()
3.定義模型類:使用declarative_base函數生成一個模型類的基類,以便模型類映射到數據庫中,且必須使用__tablename__指定表名(一個類對應數據庫中一張表,不一樣的類實例對應表中不一樣的記錄)。
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base # 數據庫鏈接信息 HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # 數據庫鏈接字符串 # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) # 建立一個engine對象 engine = create_engine(DB_URI) # 建立全部模型類的基類 Base = declarative_base(engine) # 注意如下定義全是在類中直接進行的,沒有在__init__等方法中進行 class Person(Base): # 使用__table__name指定表名 __tablename__ = 'person' # 定義屬性字段id爲整型、主鍵、自動增加 id = Column(Integer, primary_key=True, autoincrement=True) # 定義屬性字段name爲最長50個字符的字符串類型,且非空 name = Column(String(50), nullable=False) # 定義屬性字段age爲整型 age = Column(Integer) # 刪除表,不用特意指定表,在加載Python文件時會自動檢查定義了哪些表,並刪除這些表 Base.metadata.drop_all() # 將全部模型映射到數據庫中,而且相同的模型類只在第一次執行時會生效,即若是第一次執行後, # 又對類進行了修改,從新運行程序執行metadata.create_all()後並不會把更新的內容映射到數據庫中,前提是數據庫中的表沒有被刪除 Base.metadata.create_all()
4.經常使用數據類型:數據類型對應的類直接從模塊sqlalchemy中導入便可。
5.Column經常使用參數:Column的第一個參數name用來指定數據中的屬性名,若是不指定則默認爲該屬性變量名爲屬性名。
6.增刪改查操做:使用sessionmaker建立session,並在session中進行增刪改查操做,注意若是涉及到修改數據庫,必定要commit後才能在數據庫生效。
增刪改查簡單示例(數據庫鏈接代碼和模型類代碼見前面的代碼示例):
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine(DB_URI) # 別忘了實例化後再一次調用(加括號),會調用類的__call__生成session session = sessionmaker(engine)() # 增長數據 def add_data(): p = Person(name='Jason', age=19) # 添加一條數據到內存中 session.add(p) # 添加多條數據到內存中 p1 = Person(name='Mickle', age=20) p2 = Person(name='Marya', age=21) session.add_all([p1, p2]) # 提交到數據庫中 session.commit() # 刪除數據 def del_data(): p = session.query(Person).first() # 直接刪除提交便可 session.delete(p) session.commit() # 修改數據 def update_data(): p = session.query(Person).first() # 獲取對象後,直接修改提交便可 p.name = 'JiuyunnZhao' session.commit() # 查詢數據 def search_data(): # 查找模型類對應表的的全部數據(可用for遍歷) # persons = session.query(Person).all() # 查詢知足某個條件的全部數據(可for遍歷),查詢條件只有參數和一個等號(這種方式比較簡單,由於只針對一個類) # persons = session.query(Person).filter_by(name='Mickle').all() # 查詢知足某個條件的全部數據(可for遍歷),查詢條件類名.參數和雙等號(filter中的條件能夠更加複雜,這裏只是簡單舉例) # persons = session.query(Person).filter(Person.name == 'Mickle').all() # for p in persons: # print(p) # 根據主鍵查詢某一條數據,沒有對應的主鍵則返回None # p = session.query(Person).get(100) # 獲取某張表的第一條數據 p = session.query(Person).first() p = session.query(Person).filter(Person.name == 'Mickle').first() p = session.query(Person).filter_by(name='Mickle').first() print(p) # 測試代碼 if __name__ == '__main__': add_data() # del_data() # update_data() # search_data()
7.聚合函數:從sqlalchemy中導入func,func中有許多聚合函數可使用。其實func中沒有「真正」的聚合函數,都是MySQL中的函數,也就是或MySQL中的聚合函數均可以在func中找到和使用。
8.filter中的條件過濾(注意不是filter_by方法):
9.外鍵及外鍵約束:在想要定義爲外鍵的列中傳入參數ForeignKey('tablename.column_name')便可,若是想要定義外鍵約束,在ForeignKey中指定參數ondelete爲相應約束便可,默認約束爲RESTRICT。
from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) engine = create_engine(DB_URI) Base = declarative_base(engine) # 父表 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 子表 class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外鍵列,意爲一個用戶能夠有多篇文章,注意此列的類型應該對應父表的主鍵類型一致
# 注意這裏是「表名.屬性名」,而不是「類名.屬性變量名」 user_id = Column(Integer, ForeignKey('user.user_id', ondelete='CASCADE'))
10.外鍵關係:經過relationship將兩個存在外鍵關聯的兩張表創建一個關係屬性,並經過這個屬性去進行互相訪問。
一對一關係簡單示例:
# 一對一關係示例1:一張表定義外鍵,另外一張表定義一對一關係,即uselist=False class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 添加一個到模型Article的一對一關係,關鍵在於uselist=False,由於默認是True,那就是一對多了 article = relationship('Article', uselist=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外鍵列「表名.屬性名」,而不是「類名.屬性變量名」 user_id = Column(Integer, ForeignKey('user.user_id')) # 添加一個到模型User的關係,因爲User類中定義了一對一uselist=False,因此這個關係天然也是一對一了,也不用再指定uselist=False author = relationship('User') # 一對一示例2:利用反向引用函數backref創建一對一關係 # backref函數中的參數和relationship中的參數是一致的,relationship中可用的參數它均可以用 from sqlalchemy.orm import sessionmaker, relationship, backref class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外鍵列 user_id = Column(Integer, ForeignKey('user.user_id')) # 這裏backref的使用至關於在User類中創建了一個名爲article的關係,且參數uselist爲False author = relationship('User', backref=backref('article', uselist=False))
一對多關係簡單示例
# 一對多關係示例1 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 添加一個到模型Article的關係,一對多,表示「多」的的變量articles其實繼承自list,因此append等方法也適用這個屬性 articles = relationship('Article') class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外鍵列,注意這裏是「表名.屬性名」,而不是「類名.屬性變量名」 user_id = Column(Integer, ForeignKey('user.user_id')) # 添加一個到模型User的關係,多對一 author = relationship('User') # 一對多關係示例2 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外鍵列,注意這裏是「表名.屬性名」,而不是「類名.屬性變量名」 user_id = Column(Integer, ForeignKey('user.user_id')) # 反向引用,backref參數就至關於自動給User模型添加了一個名爲articles且關聯到User模型的的關係 author = relationship('User', backref='articles') # 使用示例,如下代碼將在article表中添加兩條數據 user =User(username='Mickle') article1 = Article(title='aaa', content='1111') article2 = Article(title='bbb', content='222') user.articles.append(article1) user.articles.append(article2) session.add(user) session.commit()
多對多關係簡單示例
# 多對多關係示例:一篇文章能夠有多個標籤,一個標籤也能夠用於多篇文章 from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey, Table from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)() class Article(Base): __tablename__ = 'article' artcle_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) # 與Tag創建關聯關係和反向引用關係,並指明中間表爲article_tag # 這個關係能夠定義在關聯的兩張表中的任意一張表中均可以 tags = relationship('Tag', backref='articles', secondary=article_tag) class Tag(Base): __tablename__ = 'tag' tag_id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(50), nullable=False) # 經過類Table來生成一箇中間表 article_tag = Table( 'article_tag', # 表名 Base.metadata, # 繼承的模型類型 # 定義中間表中的列,聲明此列關聯到表article的列article_id,並指明以此列來做爲複合主鍵的其中一列 Column('article_id', Integer, ForeignKey('article.article_id'), primary_key=True), # 定義中間表中的列,聲明此列關聯到表tag的列tag_id,並指明以此列來做爲複合主鍵的其中一列 Column('tag_id', Integer, ForeignKey('tag.tag_id'), primary_key=True) ) # 添加數據到數據庫中 article1 = Article(title='my article 1') article2 = Article(title='my article 2') tag1 = Tag(name='my tag 1') tag2 = Tag(name='my tag 2') article1.tags.append(tag1) article1.tags.append(tag2) article2.tags.append(tag1) article2.tags.append(tag2) session.add(article1) session.add(article2) session.commit()
11.查詢排序:默認升序,降序通常使用對應屬性的desc()方法便可。
升序降序簡單示例:
# 如下列子以模型類Article中的字段create_time做爲示例(字符串中的屬性名是數據庫中的屬性名而不是變量名(沒有定義時二者是同樣的)) # 方式一:在session中使用order_by查詢排序 # 升序 articles = session.query(Article).order_by(Article.create_time).all() articles = session.query(Article).order_by('create_time').all() # 降序) articles = session.query(Article).order_by(Article.create_time.desc()).all() articles = session.query(Article).order_by('-create_time').all() # 方式2、在模型類中使用__mapper_args__的order_by指定查詢排序 class Article(Base): __tablename__ = 'article' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) create_time = Column(DateTime, nullable=False, default=datetime.now) __mapper_args__ = { 'order_by': create_time, # 升序 # 'order_by': create_time.desc(), # 降序 } # 方式3、使用模型類中relationship的roder_by進行指定查詢排序 class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) create_time = Column(DateTime, nullable=False, default=datetime.now) user_id = Column(Integer, ForeignKey('user.id')) author = realtionship('User', backref=backref('articles', order_by=create_time)) # 升序 # author = realtionship('User', backref=backref('articles', order_by=create_time.desc())) # 降序
12.query對象經常使用方法:
13.高級查詢:
4、Flask-SQLAlchemy使用
因爲Flask-SQLAlchemy實際上是SQLAlchemy在外面進行了一層封裝,以便更好的適用於flask,因此Flask-SQLAlchemy和SQLAlchemy在使用上除了最外層封裝的定義外都是同樣的,下面只講一些常須要注意的不一樣之處
安裝:pip install flask-sqlalchemy
1. 配置:須要在配置文件中配置數據庫鏈接字符串「SQLALCHEMY_DATABASE_URI」,其中driver爲Python2的mysqldb,Python3的pymysql,具體以安裝的插件爲準。
# 數據庫鏈接固定格式格式字符串 # dialect+driver://username:password@host:port/database DIALECT = 'mysql' DRIVER = 'mysqldb' USERNAME = 'root' PASSWORD = 123456 HOST = '127.0.0.1' PORT = '3306' DATABASE = 'db_demo1' SQLALCHEMY_DATABASE_URI = '{dialect}+{driver}://{username}:{password}@{host}:{port}/{database}?charset=utf8'.format( dialect=DIALECT, driver=DRIVER, username=USERNAME, password=PASSWORD, host=HOST, port=PORT, database=DATABASE )
2.使用:Column、relationship等均可以直接在「from flask_sqlalchemy import SQLAlchemy」的SQLAlchemy實例中直接使用
簡單示例(配置信息寫在了配置文件config.py中了)
from flask import Flask from flask_sqlalchemy import SQLAlchemy import config app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app) db.create_all() class User(db.Model): __tablename__ = 'user' # 設置表名,未設置則以類名全小寫爲表名 id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定義列id,整型,主鍵,自增加 username = db.Column(db.String(100), nullable=False) # 定義列username,字符型(最大100個字符),非空