flask-sqlachemy数据库操作

flask-sqlachemy

1 ORM

flask-sqlachemy让flask框架可以继承sqlachemy框架
sqlachemy是python中最著名的ORM框架
ORM:对象关系映射(Object-Relation Mapping)可以允许开发者使用原生代码的方式来操作数据库
优点:开发者不用写SQL语句,而且也不需要学习其他数据库的SQL语法
缺点:存在一定的性能缺失
在这里插入图片描述

2 .创建连接

需要安装

pip install flask_sqlalchemy
pip install flask_mysqldb

py代码

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

# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://数据库用户名:密码@127.0.0.1:3306/test23'

# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 创建数据连接
db = SQLAlchemy(app)
@app.route('/')
def index():
    return 'index'


if __name__ == '__main__':
    app.run(debug=True)

3,基础操作

py代码

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:root:[email protected]:3306/test23'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 创建数据连接
db = SQLAlchemy(app)


# 映射关系 类>表 属性>字段 对象>记录
class User(db.Model):
    __tablename__ = 't_user'  # 设置表名,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值


@app.route('/')
def index():
    # 删除所有继承db.Model的表
    db.drop_all()

    # 创建所有继承db.Model的表
    db.create_all()

    # 创建对象(模型)
    user1 = User(name='zs')

    # 将对象添加到会话(事物)中
    db.session.add(user1)

    # 提交会话(事物),必须提交,否则数据库不会变化
    db.session.commit()
    return 'index'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

4,增删改

py代码

  # 增加对象
    user2 = User(name='ls')
    db.session.add(user2)
    db.session.commit()

    user3 = User(name='ls')
    db.session.add(user3)
    db.session.commit()

    # 修改数据
    user2.name = 'ww'
    db.session.commit()

    # 删除数据
    db.session.delete(user2)
    db.session.commit()

5,数据查询

py代码

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test21'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# # 设置控制台是否打印底层语句
# app.config['SQLALCHEMY_ECHO'] = True

# 创建数据连接
db = SQLAlchemy(app)


# ⾃定义类 继承db.Model 对应 表
class User(db.Model):
    __tablename__ = "users" # 表名 默认使⽤类名的⼩写
    # 定义类属性 记录字段
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    email = db.Column(db.String(64))
    age = db.Column(db.Integer)
    def __repr__(self): # ⾃定义 交互模式 & print() 的对象打印
        return "(%s, %s, %s, %s)" % (self.id, self.name, self.email, self.age)

# def select():
#     # 查询所有⽤户数据
#     User.query.all()
#
#     # 查询有多少个⽤户
#     User.query.count()
#
#     # 查询第1个⽤户
#     User.query.first()
#
#     # 查询id为3的⽤户[3种⽅式]
#     User.query.get(3)  # 根据主键查询
#     User.query.filter_by(id=3).all()  # 以关键字实参形式进行匹配字段
#     User.query.filter(User.id == 3).all()  # 以恒等式形式匹配字段
#
#     # 查询名字结尾字符为g的所有⽤户[开始 /
#     User.query.filter(User.name.endswith('g')).all()
#
#     # 查询名字包含‘n'的所有项目
#     User.query.filter(User.name.contains('n').all()
#     User.query.filter(User.name.like('w%n%g').all() # 模糊查询
#
#     # 查询名字和邮箱都以li开头的所有⽤户[2种⽅式]
#     User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()
#
#     from sqlalchemy import and_
#
#     User.query.filter(and_(User.name.startswith('li'),User.email.startswith('li'))).all()
#
#     # 查询age是25 或者 `email`以`itheima.com`结尾的所有⽤户
#     from sqlalchemy import or_
#     User.query.filter(or_(User.age==25,User.email.endswith('itheima.com'))).all()
#
#     # 查询名字不等于wang的所有⽤户[2种⽅式]
#     from sqlalchemy import not_
#     User.query.filter(not_(User.name=='wang')).all()
#
#     User.query.filter(User.name != 'wang').all()
#
#     # 查询id为[1, 3, 5, 7, 9]的⽤户
#     User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()
#
#     # 所有⽤户先按年龄从⼩到⼤, 再按id从⼤到⼩排序, 取前5个
#     User.query.order_by(User.age,User.id.desc()).limit(5).all()
#
#     # 分⻚查询, 每⻚3个, 查询第2⻚的数据
#     pn = User.query.paginate(2,3)
#     pn.pages
#     pn.page
#     pn.items

if __name__ == '__main__':
    # 删除所有表
    db.drop_all()
    # 创建所有表
    db.create_all()
    # 添加测试数据
    user1 = User(name='wang', email='[email protected]', age=20)
    user2 = User(name='zhang', email='[email protected]', age=33)
    user3 = User(name='chen', email='[email protected]', age=23)
    user4 = User(name='zhou', email='[email protected]', age=29)
    user5 = User(name='tang', email='[email protected]', age=25)
    user6 = User(name='wu', email='[email protected]', age=25)
    user7 = User(name='qian', email='[email protected]', age=23)
    user8 = User(name='liu', email='[email protected]', age=30)
    user9 = User(name='li', email='[email protected]', age=28)
    user10 = User(name='sun', email='[email protected]', age=26)
    # ⼀次添加多条数据
    db.session.add_all([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10])
    db.session.commit()
    # select()
    app.run(debug=True)

6一对多

  1. 定义外键
	use_id = db.Column(db.Integer,db.ForeignKey('t_user.id')) # 定义外健,必须在多的一方
  1. 定义关系属性
 addreses = db.relationship('Addres') # 定义关系属性
  1. 1 反向关系属性
addreses = db.relationship('Addres',backref='user_info')
  1. 添加到关系属性列表进行关联
	user1 = User(name='zs')
	adr1 = Addres(name='中关村1号')
	adr2 = Addres(name='华强北5号')
	
	user1.addreses.append(adr1)
	user1.addreses.append(adr2)
  1. 使用关系属性查询
	User.query.filter_by(name='zs').first()
    adrs = user1.addreses
    for adr in adrs:
        print(adr.name)

6.1 实例

py代码

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test23'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 设置控制台是否打印底层语句
# app.config['SQLALCHEMY_ECHO'] = True
# 创建数据连接
db = SQLAlchemy(app)


# 映射关系 类>表 属性>字段 对象>记录
class User(db.Model):
    __tablename__ = 't_user'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值
    addreses = db.relationship('Addres') # 定义关系属性

class Addres(db.Model):
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值
    use_id = db.Column(db.Integer,db.ForeignKey('t_user.id')) # 定义外健,必须在多的一方

@app.route('/')
def index():
    # 删除所以继承db.Model的表
    db.drop_all()

    # 创建所以继承db.Model的表
    db.create_all()

    # 创建对象(模型)
    user1 = User(name='zs')
    adr1 = Addres(name='中关村1号')
    adr2 = Addres(name='华强北5号')

    user1.addreses.append(adr1)
    user1.addreses.append(adr2)

    db.session.add_all([adr1,adr2,user1]) # 使用的是add_all([])

    db.session.commit()

    User.query.filter_by(name='zs').first()
    adrs = user1.addreses
    for adr in adrs:
        print(adr.name)

    return 'index'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

7综合案例>图书管理

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    <label>作者:</label>
    <input type="text" name="author" placeholder="请输入作者名"><br/>
    <label>书名:</label>
    <input type="text" name="book" placeholder="请输入书名"><br/>
    <input type="submit" value="添加">
</form>
<ul>
    {% for author in authors %}
    <li>{{ author.name }}<a href="{{ url_for('delete_author',author_id=author.id) }}">删除</a></li>
        {% for book in author.books %}
        <ul>
        <li>{{ book.name }}<a href="{{ url_for('delete_book',book_id=book.id) }}">删除</a></li>
        </ul>
        {% endfor %}
    {% endfor %}
</ul>
{% for message in get_flashed_messages() %}
<script>alert('{{ message }}')</script>
{% endfor %}

</body>
</html>

py代码

from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/book23'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 设置控制台是否打印底层语句
# app.config['SQLALCHEMY_ECHO'] = True
# 创建数据连接
db = SQLAlchemy(app)

# flash使用的是session保存内容,所以一定要设在密钥
app.secret_key = 'test'


# 映射关系 类>表 属性>字段 对象>记录
class Author(db.Model):
    __tablename__ = 't_author'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值
    books = db.relationship('Book', backref='author_info')


class Book(db.Model):
    __tablename__ = 't_book'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值
    author_id = db.Column(db.Integer, db.ForeignKey('t_author.id'))


@app.route('/', methods=['GET', 'POST'])
def index():
    method = request.method
    if method == 'GET':
        authors = Author.query.all()
        return render_template('book.html', authors=authors)

    author_name = request.form.get('author')
    book_name = request.form.get('book')

    if not all([author_name, book_name]):
        flash('参数错误!')
        return redirect(url_for('index'))

    # print(author_name)
    # print(Author.query.all())
    # for i in Author.query.all():
    #     print(i.name)
    try:
        author = Author.query.filter_by(name=author_name).first()
        # print(author)
    except Exception as e:
        flash('查询错误')
        return redirect(url_for('index'))
    try:

        if author:
            book = Book(name=book_name)
            author.books.append(book)
            db.session.add(book)
            db.session.commit()
        else:
            author = Author(name=author_name)
            book = Book(name=book_name)
            author.books.append(book)
            db.session.add_all([book, author])
            db.session.commit()
    except Exception as e:
        flash('操作失败')
        db.session.rollback()
    return redirect(url_for('index'))


@app.route('/delete_book/<int:book_id>')
def delete_book(book_id):
    try:
        book = Book.query.get(book_id)
        db.session.delete(book)
        db.session.commit()
    except Exception as e:
        flash('删除书籍失败')
        db.session.rollback()
    return redirect(url_for('index'))


@app.route('/delete_author/<int:author_id>')
def delete_author(author_id):
    try:
        author = Author.query.get(author_id)
    except Exception as e:
        flash('查询失败')
        return redirect(url_for('index'))
    try:
        for book in author.books:
            db.session.delete(book)
            
        db.session.delete(author)
        db.session.commit()
    except Exception as e:
        flash('删除作者失败')
        db.session.rollback()
    return redirect(url_for('index'))


if __name__ == '__main__':
    # 删除所以继承db.Model的表
    db.drop_all()

    # 创建所以继承db.Model的表
    db.create_all()

    # ⽣成数据
    au1 = Author(name="老王")
    au2 = Author(name="老尹")
    au3 = Author(name="老刘")
    # 把数据提交给⽤户会话
    db.session.add_all([au1, au2, au3])
    # 提交会话
    db.session.commit()
    bk1 = Book(name='⽼王回忆录', author_id=au1.id)
    bk2 = Book(name='我读书少,你别骗我', author_id=au1.id)
    bk3 = Book(name='如何才能让⾃⼰更骚', author_id=au2.id)
    bk4 = Book(name='怎样征服美丽少⼥', author_id=au3.id)
    bk5 = Book(name='如何征服英俊少男', author_id=au3.id)
    # 把数据提交给⽤户会话
    db.session.add_all([bk1, bk2, bk3, bk4, bk5])
    # 提交会话
    db.session.commit()

    app.run(host='0.0.0.0', port=8080, debug=True)

8多对多

py代码

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test23'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 创建数据连接
db = SQLAlchemy(app)


# 映射关系 类>表 属性>字段 对象>记录
class Student(db.Model):
    __tablename__ = 't_student'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值
    courses = db.relationship('Course',backref='students',secondary='t_student_course')

class Course(db.Model):
    __tablename__ = 't_course'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)

class Student_course(db.Model):
    __tablename__ = 't_student_course'  # 设置表面,表名默认为类名小写
    stu_id = db.Column(db.Integer, db.ForeignKey('t_student.id'),primary_key=True)
    cour_id = db.Column(db.Integer, db.ForeignKey('t_course.id'), primary_key=True)

if __name__ == '__main__':
    # 删除所以继承db.Model的表
    db.drop_all()

    # 创建所以继承db.Model的表
    db.create_all()

    stu1 = Student(name='zs')
    stu2 = Student(name='ls')
    cour1 = Course(name='c')
    cour2 = Course(name='python')
    cour3 = Course(name='java')

    stu1.courses.append(cour1)
    stu1.courses.append(cour2)
    stu2.courses.append(cour2)
    stu2.courses.append(cour3)

    db.session.add_all([stu1,stu2,cour1,cour2,cour3])
    db.session.commit()

    cours = stu1.courses
    for cour in cours:
        print(cour.name)
    app.run(host='0.0.0.0', port=8080, debug=True)

9数据库迁移

在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。
更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。
在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。
为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。
首先要在虚拟环境中安装Flask-Migrate。

pip install flask-migrate

代码文件内容:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Manager
app = Flask(__name__)
# 设置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test20'
# 设置是否跟踪数据库变化,开启非常影响性能,不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 创建数据连接
db = SQLAlchemy(app)
mgr = Manager(app)

# 初始化迁移器
Migrate(app,db)

# 管理器生成迁移命令
mgr.add_command('mc',MigrateCommand)

# 映射关系 类>表 属性>字段 对象>记录
class User(db.Model):
    __tablename__ = 't_user'  # 设置表面,表名默认为类名小写
    id = db.Column(db.Integer, primary_key=True)  # 标识为主键
    name = db.Column(db.String(40), unique=True, nullable=False)  # 标识唯一且不能为空值


@app.route('/')
def index():

    return 'index'


if __name__ == '__main__':
    # # 删除所以继承db.Model的表
    # db.drop_all()
    #
    # # 创建所以继承db.Model的表
    # db.create_all()

    # app.run(host='0.0.0.0', port=8080, debug=True)
    mgr.run()

1.创建迁移仓库

这个命令会创建migrations文件夹,所有迁移文件都放在里面.(在终端中输入以下代码)

python database.py mc init

2.生成迁移版本

python xx.py mc migrate -m "注释"

3.执行升级操作

python xx.py mc upgrade

实际操作顺序:

1.python 文件 mc init
2.python 文件 mc migrate -m"版本名(注释)"
3.python 文件 mc upgrade 然后观察表结构
4.根据需求修改模型
5.python 文件 mc migrate -m"新版本名(注释)"
6.python 文件 mc upgrade 然后观察表结构
7.若返回版本,则利用 python 文件 mc history查看版本号
8.python 文件 mc downgrade(upgrade) 版本号

猜你喜欢

转载自blog.csdn.net/weixin_43751803/article/details/86512505