數據庫操作Flask-SQLAlchemy之模型聲明及數據庫表的生成與刪除


ORM

ORM 全拼Object-Relation Mapping,中文意為 對象-關系映射。主要實現模型對象到關系數據庫數據的映射

優點 :

  • 只需要面向對象編程, 不需要面向數據庫編寫代碼.

    • 對數據庫的操作都轉化成對類屬性和方法的操作.

    • 不用編寫各種數據庫的sql語句.

  • 實現了數據模型與數據庫的解耦, 屏蔽了不同數據庫操作上的差異.

    • 不再需要關注當前項目使用的是哪種數據庫。

    • 通過簡單的配置就可以輕松更換數據庫, 而不需要修改代碼.

缺點 :

  • 相比較直接使用SQL語句操作數據庫,有性能損失.

  • 根據對象的操作轉換成SQL語句,根據查詢的結果轉化成對象, 在映射過程中有性能損失.

Flask-SQLAlchemy

flask默認提供模型操作,但是並沒有提供ORM,所以一般開發的時候我們會采用flask-SQLAlchemy模塊來實現ORM操作。

SQLAlchemy是一個關系型數據庫框架,它提供了高層的 ORM 和底層的原生數據庫的操作。flask-sqlalchemy 是一個簡化了 SQLAlchemy 操作的flask擴展。

SQLAlchemy: https://www.sqlalchemy.org/

中文文檔: https://www.osgeo.cn/sqlalchemy/index.html

安裝 flask-sqlalchemy【清華源】
pip3 install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

如果連接的是 mysql 數據庫,需要安裝 mysqldb 驅動
pip3 install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple



安裝flask-mysqldb時,注意
安裝 flask-mysqldb的時候,python底層依賴於一個底層的模塊 mysql-client模塊
如果沒有這個模塊,則會報錯如下:
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-21hysnd4/mysqlclient/

解決方案:sudo apt-get install libmysqlclient-dev python3-dev

 運行上面的安裝命令如果再次報錯如下:
 dpkg 被中斷,您必須手工運行 ‘sudo dpkg --configure -a’ 解決此問題。

 則根據提示執行命令以下命令,再次安裝mysqlclient
 sudo dpkg --configure -a
 apt-get install libmysqlclient-dev python3-dev

 解決了mysqlclient問題以后,重新安裝 flask-mysqldb即可。
 1pip3 install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple

數據庫連接設置

在 Flask-SQLAlchemy 中,數據庫使用URL指定,而且程序使用的數據庫必須保存到Flask配置對象的 SQLALCHEMY_DATABASE_URI 鍵中

config.py,配置文件代碼:

class Config(object):
    DEBUG = True
    SECRET_KEY = "*(%#4sxcz(^(#$#8423"
    # 數據庫鏈接配置 = 數據庫名稱://登錄賬號:登錄密碼@數據庫主機IP:數據庫訪問端口/數據庫名稱?charset=編碼類型
    SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
  # 動態追蹤修改設置,如未設置只會提示警告
  SQLALCHEMY_TRACK_MODIFICATIONS = True
  #查詢時會顯示原始SQL語句
  SQLALCHEMY_ECHO = True

  配置完成需要去 MySQL 中創建項目所使用的數據庫
  $ mysql -uroot -p123
  mysql > create database students charset=utf8mb4;

常用的SQLAlchemy列約束選項

數據庫基本操作

  • 在Flask-SQLAlchemy中,添加、修改、刪除操作,均由數據庫會話管理。

    • 會話用 db.session 表示。在准備把數據寫入數據庫前,要先將數據添加到會話中然后調用 db.commit() 方法提交會話。

  • 在 Flask-SQLAlchemy 中,查詢操作是通過 query 對象操作數據。

    • 最基本的查詢是返回表中所有數據,可以通過過濾器進行更精確的數據庫查詢。

定義模型類

from flask import Flask,render_template,request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

class Config():
    DEBUG = True
    # 數據庫鏈接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://賬號:密碼@IP/數據庫名?編碼"
    SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    # 動態追蹤修改設置,如未設置只會提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)

db = SQLAlchemy()
db.init_app(app)

"""創建模型類"""
class Student(db.Model):
    __tablename__ = "tb_student"
    id = db.Column(db.Integer, primary_key=True,comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    age = db.Column(db.Integer, comment="年齡")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    money = db.Column(db.DECIMAL(8,2), nullable=True, comment="錢包")

    def __repr__(self):
        return self.name

class Teacher(db.Model):
    __tablename__ = "tb_teacher"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    option = db.Column(db.Enum("講師","助教","班主任"), default="講師", comment="教職")

    def __repr__(self):
        return self.name

class Course(db.Model):
    __tablename__ = "tb_course"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), unique=True, comment="課程名稱")
    price = db.Column(db.Numeric(6, 2))

    def __repr__(self):
        return self.name

@app.route("/")
def index():
    return "Ok"

if __name__ == '__main__':
    # with app.app_context():
    #     db.create_all() # 根據模型創建所有的數據表
    #     # db.drop_all()   # 刪除模型對應的所有數據表
    app.run()
模型類

數據基本操作

 

 

 

 

from flask import Flask,render_template,request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

class Config():
    DEBUG = True
    # 數據庫鏈接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://賬號:密碼@IP/數據庫名?編碼"
    SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    # 動態追蹤修改設置,如未設置只會提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)

db = SQLAlchemy()
db.init_app(app)

"""創建模型類"""
class Student(db.Model):
    __tablename__ = "tb_student"
    id = db.Column(db.Integer, primary_key=True,comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    age = db.Column(db.Integer, comment="年齡")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    money = db.Column(db.DECIMAL(8,2), nullable=True, comment="錢包")

    def __repr__(self):
        return self.name

class Teacher(db.Model):
    __tablename__ = "tb_teacher"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    option = db.Column(db.Enum("講師","助教","班主任"), default="講師", comment="教職")

    def __repr__(self):
        return self.name

class Course(db.Model):
    __tablename__ = "tb_course"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), unique=True, comment="課程名稱")
    price = db.Column(db.Numeric(6, 2))

    def __repr__(self):
        return self.name

@app.route("/")
def index():
    """數據庫基本操作"""

    """添加數據"""
    # 添加一條數據
    # student1 = Student(name="xiaohong",age=16,money=100,sex=True)
    # db.session.add(student1)
    # db.session.commit()

    # 批量添加多條數據
    # data_list = [
    #     Student(name="xiaohui1號",age=16,money=1000, sex=True),
    #     Student(name="xiaohui2號",age=16,money=1000, sex=True),
    #     Student(name="xiaohui3號",age=16,money=1000, sex=True),
    #     Student(name="xiaohui4號",age=16,money=1000, sex=True),
    #     Student(name="xiaohui5號",age=16,money=1000, sex=True),
    #     Student(name="xiaohui6號",age=16,money=1000, sex=True),
    # ]
    # db.session.add_all(data_list)
    # db.session.commit()

    """查詢數據"""
    # 根據主鍵ID查詢一條數據,如果ID不存在,則返回None不會報錯!
    # student = Student.query.get(100)
    # if student is None:
    #     print("當前學生不存在!")
    # else:
    #     print(student)
    #     print(student.name,student.age) # 獲取屬性

    # 根據查詢條件獲取一條數據
    # 模型.query.filter(模型.字段==條件值).first()
    # student = Student.query.filter(Student.id==1).first()
    # print(student)
    # print(student.name,student.money)

    # 根據查詢條件獲取多條數據
    # 模型.query.filter(模型.字段==條件值).all()
    # student_list = Student.query.filter(Student.id < 5).all()
    # print(student_list)
    # """打印效果;
    # [xiaoming, xiaohong, xiaohui1號, xiaohui2號]
    # """
    # for student in student_list:
    #     print(student.name, student.money)

    """更新數據"""
    # 先查詢后修改
    # student = Student.query.filter(Student.name=="xiaoming").first()
    # student.money+=1000
    # db.session.commit()

    # 直接根據條件修改
    # Student.query.filter(Student.name=="xiaoming",Student.money==1100).update({Student.money:2000}) # 樂觀鎖
    # 實現類似django的F函數效果,字段值累加
    # Student.query.filter(Student.name=="xiaoming").update({Student.money:Student.money+500}) # 樂觀鎖
    # db.session.commit()

    """刪除數據"""
    # 先查詢后刪除
    # student = Student.query.filter(Student.name=="xiaohui6號").first()
    # db.session.delete(student)
    # db.session.commit()

    # 直接根據條件進行刪除操作
    Student.query.filter(Student.name=="xiaohui5號").delete()
    db.session.commit()

    return "Ok"

if __name__ == '__main__':
    # with app.app_context():
    #     db.create_all() # 根據模型創建所有的數據表
    #     # db.drop_all()   # 刪除模型對應的所有數據表
    app.run()
增刪查改

 

分組查詢和分組查詢結果過濾

一般分組都會結合聚合函數來一起使用。SQLAlchemy中所有的聚合函數都在func模塊中聲明的。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

class Config():
    # DEBUG調試模式
    DEBUG = True
    # json多字節轉unicode編碼
    JSON_AS_ASCII = False
    # 數據庫鏈接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://賬號:密碼@IP/數據庫名?編碼"
    SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    # 動態追蹤修改設置,如未設置只會提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)
db = SQLAlchemy()
db.init_app(app)

"""創建模型類"""
class Student(db.Model):
    __tablename__ = "tb_student"
    id = db.Column(db.Integer, primary_key=True,comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    age = db.Column(db.Integer, comment="年齡")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    money = db.Column(db.DECIMAL(8,2), nullable=True, comment="錢包")

    def __repr__(self):
        return self.name

class Teacher(db.Model):
    __tablename__ = "tb_teacher"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), comment="姓名")
    sex = db.Column(db.Boolean, default=False, comment="性別")
    option = db.Column(db.Enum("講師","助教","班主任"), default="講師", comment="教職")

    def __repr__(self):
        return self.name

class Course(db.Model):
    __tablename__ = "tb_course"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(250), unique=True, comment="課程名稱")
    price = db.Column(db.Numeric(6, 2))

    def __repr__(self):
        return self.name

@app.route("/")
def index():
    from sqlalchemy import func
    """ group_by 分組查詢"""
    # 查詢男生和女生的最大年齡   Student.query.group()以下Student不支持聚合查詢
    # ret = db.session.query(Student.sex,func.max(Student.age)).group_by(Student.sex).all()
    # print(ret)

    # 查詢出男生和女生年齡大於18的人數
    # having是針對分組的結果進行過濾處理,所以having能調用的字段,必須是分組查詢結果中的字段,否則報錯!!
    # ret = db.session.query(Student.sex,Student.age,func.count(Student.age)).group_by(Student.sex,Student.age).having(Student.age>18).all()
    # print(ret)

    """執行原生SQL語句,返回結果不是模型對象, 是列表和元祖"""
    # 查詢多條
    # ret = db.session.execute("select id,name,age,IF(sex,'男','女') from tb_student").fetchall()
    # print(ret)
    # # 查詢單條
    # ret = db.session.execute("select * from tb_student where id = 3").fetchone()
    # print(ret)

    # 添加/修改/刪除
    # db.session.execute("UPDATE tb_student SET money=(money + %s) WHERE age = %s" % (200, 22))
    # db.session.commit()

    # 查詢出女生和男生中大於18歲的人數
    ret = db.session.execute("SELECT IF(sex,'男','女'), count(id) from (SELECT id,name,age,sex FROM `tb_student` WHERE age>18) as stu group by sex").fetchall()
    print(ret)
    return "Ok"

if __name__ == '__main__':

    app.run()
分組查詢以及原生sql語句

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM