Flask框架——(數據庫)

Flask框架——(數據庫)

1. MySQL簡介

介紹:
MySQL是⼀個關係型數據庫管理系統,由瑞典MySQL AB公司開發,後來被Sun公司收購,Sun公司後來⼜被Oracle公司收購,⽬前屬於Oracle旗下產品。

特點:

  • 使用C和C++編寫,並使用了多種編譯器進行測試,保證源代碼的可移植性。
  • 支持多種操作系統,如Linux、Windows、AIX、FreeBSD、HP-UX、MacOS、NovellNetware、OpenBSD、OS/2 Wrap、Solaris等
  • 爲多種編程語言提供了API,如C、C++、Python、Java、Perl、PHP、Eiffel、Ruby等
  • 支持多線程,充分利用CPU資源
  • 優化的SQL查詢算法,有效地提高查詢速度
  • 提供多語言支持,常見的編碼如GB2312、BIG5、UTF8
  • 提供TCP/IP、ODBC和JDBC等多種數據庫連接途徑
  • 提供用於管理、檢查、優化數據庫操作的管理工具
  • 大型的數據庫。可以處理擁有上千萬條記錄的大型數據庫
  • 支持多種存儲引擎
  • MySQL 軟件採用了雙授權政策,它分爲社區版和商業版,由於其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,一般中小型網站的開發都選擇MySQL作爲網站數據庫
  • MySQL使用標準的SQL數據語言形式
  • Mysql是可以定製的,採用了GPL協議,你可以修改源碼來開發自己的Mysql系統
  • 在線DDL更改功能
  • 複製全局事務標識
  • 複製無崩潰從機
  • 複製多線程從機

2. SQLAlchemy介紹和基本使用

2-1. SQLAlchemy介紹和安裝

介紹:
數據庫是一個網站的基礎。Flask可以使用很多種數據庫。比如MySQL,MongoDB,SQLite,PostgreSQL等。這裏我們以MySQL爲例進行講解。而在Flask中,如果想要操作數據庫,我們可以使用ORM來操作數據庫,使用ORM操作數據庫將變得非常簡單。

安裝:

  • mysql:如果是在windows上,到官網下載。如果是ubuntu,通過命令sudo apt-get install mysql-server libmysqlclient-dev -yq進行下載安裝。
  • pymysql:pymysql是用Python來操作mysql的包,因此通過pip來安裝,命令如下:pip3 install pymysql
  • SQLAlchemy:SQLAlchemy是一個數據庫的ORM框架,我們在後面會用到。安裝命令爲:pip3 install SQLAlchemy。

2-2. 通過SQLAlchemy連接數據庫

代碼示例:

from sqlalchemy import create_engine

# 數據庫的配置變量
HOSTNAME = '127.0.0.1'
PORT     = '3306'
DATABASE = 'demo0417'
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)

# 創建數據庫引擎
engine = create_engine(DB_URI)

#創建連接
with engine.connect() as con:
    result = con.execute('select * from students')
    print(result.fetchone())

代碼講解:

  • create_engine:sqlalchemy中導⼊create_engine,⽤這個函數來創建引擎,需要滿足特定的格式(dialect+driver://username:password@host:port/database?charset=utf8)
  • engine.connect():連接數據庫

2-3. SQLAlchemy執⾏原⽣SQL

代碼示例:

from sqlalchemy import create_engine

# 數據庫的配置變量
HOSTNAME = '127.0.0.1'
PORT     = '3306'
DATABASE = 'demo0417'
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)

#連接數據庫
engine = create_engine(DB_URI,echo=True)

# 使用with語句連接數據庫,如果發生異常會被捕獲
with engine.connect() as con:
    # 先刪除users表
    con.execute('drop table if exists authors')
    # 創建一個users表,有自增長的id和name
    con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
    # 插入兩條數據到表中
    con.execute('insert into persons(name) values("abc")')
    con.execute('insert into persons(name) values("xiaotuo")')
    # 執行查詢操作
    results = con.execute('select * from persons')
    # 從查找的結果中遍歷
    for result in results:
        print(result)

3. SQLAlchemy-ORM介紹

3-1. ORM介紹

介紹:
隨着項目越來越大,採用原生SQL的方式在代碼中會出現大量的SQL語句,對項目的進展非常不利

  • SQL語句重複利用率不高,越複雜的SQL語句條件越多,代碼越長。會出現很多相近似的SQL語句
  • 很多SQL語句是在業務邏輯中拼出來的,如果有數據庫需要更改,就要去修改這些邏輯,很容易漏掉某些SQL語句的修改
  • 寫SQL時容易忽略web安全問題

ORM: Object Relationship Mapping,對象關係映射,通過ORM我們可以通過類的方式去操作數據庫,而不用寫原生的SQL語句。通過把表映射成類,把行作爲實例,把字段作爲屬性,ORM在執行對象操作時候最終還是會把對應的操作轉換爲數據庫原生語句

ORM的優點:

  • 易用性:使用ORM做數據庫的開發可以有效的減少SQL語句,寫出來的模型也更加直觀
  • 性能損耗小
  • 設計靈活:可以輕鬆寫出來複雜的查詢
  • 可移植性:SQLAlchemy封裝了底層的數據庫實現,支持多個關係型數據庫,包括MySQL,SQLite

3-2. 使用SQLAlchemy

要使用ORM來操作數據庫,首先需要創建一個類來與對應的表進行映射。現在以User表來做爲例子,它有自增長的id、name、fullname、password這些字段,那麼對應的類爲

代碼示例:1. 創建user表

from sqlalchemy import Column,Integer,String
from constants import DB_URI
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine(DB_URI,echo=True)
# 所有的類都要繼承自`declarative_base`這個函數生成的基類
Base = declarative_base(engine)
class User(Base):
    # 定義表名爲users
    __tablename__ = 'users'

    # 將id設置爲主鍵,並且默認是自增長的
    id = Column(Integer,primary_key=True)
    # name字段,字符類型,最大的長度是50個字符
    name = Column(String(50))
    fullname = Column(String(50))
    password = Column(String(100))

    # 讓打印出來的數據更好看,可選的
    def __repr__(self):
        return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % (self.id,self.name,self.fullname,self.password)

SQLAlchemy會自動的設置第一個Integer的主鍵並且沒有被標記爲外鍵的字段添加自增長的屬性。因此以上例子中id自動的變成自增長的。以上創建完和表映射的類後,還沒有真正的映射到數據庫當中,執行以下代碼將類映射到數據庫中

代碼示例:2. 將user類映射到數據庫

Base.metadata.create_all()

代碼示例: 3. 添加數據

ed_user = User(name='ed',fullname='Ed Jones',password='edspassword')
# 打印名字
print(ed_user.name)
# 打印密碼
print(ed_user.password)
# 打印id
print(ed_user.id)

可以看到,name和password都能正常的打印,唯獨id爲None,這是因爲id是一個自增長的主鍵,還未插入到數據庫中,id是不存在的。接下來讓我們把創建的數據插入到數據庫中。和數據庫打交道的,是一個叫做Session的對象

代碼示例:4. Session對象

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)

# 或者
# Session = sessionmaker()
# Session.configure(bind=engine)

session = Session()
ed_user = User(name='ed',fullname='Ed Jones',password='edspassword')
session.add(ed_user)

現在只是把數據添加到session中,但是並沒有真正的把數據存儲到數據庫中。如果需要把數據存儲到數據庫中,還要做一次commit操作

代碼示例:5. commit,存入數據庫

session.commit()
# 打印ed_user的id
print(ed_user.id)

這時候,ed_user就已經有id。 說明已經插入到數據庫中了。有人肯定有疑問了,爲什麼添加到session中後還要做一次commit操作呢,這是因爲,在SQLAlchemy的ORM實現中,在做commit操作之前,所有的操作都是在事務中進行的,因此如果你要將事務中的操作真正的映射到數據庫中,還需要做commit操作。既然用到了事務,這裏就並不能避免的提到一個回滾操作了,那麼看以下代碼展示瞭如何使用回滾

代碼示例: 5. 回滾

# 修改ed_user的用戶名
ed_user.name = 'Edwardo'

# 創建一個新的用戶
fake_user = User(name='fakeuser',fullname='Invalid',password='12345')
# 將新創建的fake_user添加到session中
session.add(fake_user)

# 判斷`fake_user`是否在`session`中存在
print(fake_user in session)

# 從數據庫中查找name=Edwardo的用戶
tmp_user = session.query(User).filter_by(name='Edwardo')
# 打印tmp_user的name
print(tmp_user)

# 打印出查找到的tmp_user對象,注意這個對象的name屬性已經在事務中被修改爲Edwardo了。
> <User(name='Edwardo', fullname='Ed Jones', password='edspassword')>
# 剛剛所有的操作都是在事務中進行的,現在來做回滾操作
session.rollback()
# 再打印tmp_user
print(tmp_user)


# 再看fake_user是否還在session中
print(fake_user in session)

接下來看下如何進行查找操作,查找操作是通過session.query()方法實現的,這個方法會返回一個Query對象,Query對象相當於一個數組,裝載了查找出來的數據,並且可以進行迭代。具體裏面裝的什麼數據,就要看向session.query()方法傳的什麼參數了,如果只是傳一個ORM的類名作爲參數,那麼提取出來的數據就是都是這個類的實例

代碼示例:6. 查找query

for instance in session.query(User).order_by(User.id):
    print(instance) # 返回的是類的實例

# 如果傳遞了兩個及其兩個以上的對象,或者是傳遞的是ORM類的屬性,那麼查找出來的就是元組
for instance in session.query(User.name):
    print(instance)

for instance in session.query(User.name,User.fullname):
    print(instance)

for instance in session.query(User,User.name).all():
    print(instance)

# 對查找的結果(Query)做切片操作
for instance in session.query(User).order_by(User.id)[1:3]
    instance

如果想對結果進行過濾,可以使用filter_by和filter兩個方法,這兩個方法都是用來做過濾的,區別在於,filter_by是傳入關鍵字參數,filter是傳入條件判斷,並且filter能夠傳入的條件更多更靈活

代碼示例:7. filter過濾

# 第一種:使用filter_by過濾:
for name in session.query(User.name).filter_by(fullname='Ed Jones'):
    print(name)

# 第二種:使用filter過濾:
for name in session.query(User.name).filter(User.fullname=='Ed Jones'):
    print(name)

4. SQLAlchemy常用數據類型

4-1. 常用數據類型

  • Integer:整形。
  • Float:浮點類型。
  • Boolean:傳遞True/False進去。
  • DECIMAL:定點類型。
  • enum:枚舉類型。
  • Date:傳遞datetime.date()進去。
  • DateTime:傳遞datetime.datetime()進去。
  • Time:傳遞datetime.time()進去。
  • String:字符類型,使用時需要指定長度,區別於Text類型。
  • Text:文本類型。
  • LONGTEXT:長文本類型。

4-2. Column常用參數

  • default:默認值。
  • nullable:是否可空。
  • primary_key:是否爲主鍵。
  • unique:是否唯一。
  • autoincrement:是否自動增長。
  • onupdate:更新的時候執行的函數。
  • name:該屬性在數據庫中的字段映射

4-3. query可用參數

  1. 模型對象。指定查找這個模型中所有的對象。
  2. 模型中的屬性。可以指定只查找某個模型的其中幾個屬性。
  3. 聚合函數。
    • func.count:統計行的數量。
    • func.avg:求平均值。
    • func.max:求最大值。
    • func.min:求最小值。
    • func.sum:求和。

4-4. 過濾條件

過濾是數據提取的一個很重要的功能,以下對一些常用的過濾條件進行解釋,並且這些過濾條件都是隻能通過filter方法實現的

equals

query.filter(User.name == 'ed')

not equals

query.filter(User.name != 'ed')

like

query.filter(User.name.like('%ed%'))

in

query.filter(User.name.in_(['ed','wendy','jack']))
# 同時,in也可以作用於一個Query
query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%ed%'))))

not in

query.filter(~User.name.in_(['ed','wendy','jack']))

is null

query.filter(User.name==None)
# 或者是
query.filter(User.name.is_(None))

is not null

query.filter(User.name != None)
# 或者是
query.filter(User.name.isnot(None))

and

from sqlalchemy import and_
query.filter(and_(User.name=='ed',User.fullname=='Ed Jones'))
# 或者是傳遞多個參數
query.filter(User.name=='ed',User.fullname=='Ed Jones')
# 或者是通過多次filter操作
query.filter(User.name=='ed').filter(User.fullname=='Ed Jones')

or

from sqlalchemy import or_  query.filter(or_(User.name=='ed',User.name=='wendy'))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章