Flask Web视频学习(2)

数据库

ORM概述

ORM(Object-Relation Mapping):对象-关系映射,用来实现【模型对象】到【关系数据库数据】的映射(通过ORM提供的一个类映射出对应数据库中的一个表和表中的记录)。

学习了ORM,就可以不写SQL语句,但也能操作数据库。但实际是ORM帮我们完成了从高级语言到数据库语言的翻译。这一翻译过程的优点就是使开发人员的效率更高,缺点是这一翻译过程是需要耗时的,但可以忽略。

在这里插入图片描述

  • 解释: 对象关系映射模型
  • 特点:
    • 1.将类名、属性映射成数据库的表名和字段
    • 2.类的对象,会映射成为数据库表中的一行一行的数据
  • 优缺点:
    • 优点:
      • 1.不再需要编写sql语句
      • 2.不再关心使用的是什么数据库了
    • 缺点:
      • 由于不是直接通过sql操作数据库,所以有性能损失

在这里插入图片描述
在这里插入图片描述

Flask-SQLAlchemy安装及配置

ORM操作流程
  • 操作流程:
    • 1.安装扩展
      • pip install flask_sqlalchemy
      • pip install flask_mysqldb / pymysql
    • 2.设置数据库的配置信息(如数据库的账号、密码IP地址等)
    • 3.创建sqlalchemy对象db,关联app
    • 4.编写继承自db.Model的模型类,编写字段
    • 5.操作数据库
      • 增删改
      • 查询
from flask import Flask, make_response, request, session, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 1 设置数据库的配置信息
# 设置数据库的链接信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:654321@127.0.0.1:3306/python_data1" # 注意654321是自己的数据库的密码,python_data1是指定的数据库
# 该字段增加了大量的开销,未来将会被禁用。这里设置为False是为了避免debug时给我们警告
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 2 创建SQLAlchemy对象db,关联app
db = SQLAlchemy(app)

# 3 编写模型类、字段,继承自db.Model
class Student(db.Model):
	#__tablename__ = "students"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))

@app.route('/', methods=["GET", "POST"])
def hello_world():
    return "hello"


if __name__ == "__main__":

    # 删除继承自db.Model的表
    db.drop_all()

    # 4 创建数据库的表,创建的是继承自db.Model的表
    #db.create_all()
    
    app.run(debug=True)

在运行系项目之前,需要手动创建所需数据库。创建完之后运行该项目,该项目的代码最终会帮助我们在这个库中创建出数据表。
在这里插入图片描述
在这里插入图片描述
运行项目。

检查:
在这里插入图片描述

需要注意到的:

  1. 因为SQLALChemy去app身上读取了配置信息,所以需要设置到app.config身上
  2. 数据库的链接信息
  • 如果安装的是flask_mysqldb, 那么链接信息: mysql://<用户名>:<密码>@<ip地址>:<端口号>/<数据库名字>
  • 如果安装的是pymysql, 那么链接信息: mysql+pymysql://<用户名>:<密码>@<ip地址>:<端口号>/<数据库名字>
  1. 编写的模型类必须继承自db.Model才能被映射
  2. 如果不指定表名称,默认生成的就是模型类的小写,如果需要自己指定表名使用__tablename__=‘表名’
  3. ORM在进行映射的时候不能生成数据库的,只能在指定数据库中生成一个表。

数据库的基本操作

增删改
  • 全部都是使用db.session操作
  • 常见方法:
    • db.session.add(obj) 添加单个对象
    • db.session.add_all([obj1,obj2]) 添加多个对象
    • db.session.delete(obj) 删除单个对象
    • db.session.commit() 提交会话
    • db.drop_all() 删除继承自db.Model所有表
    • db.create_all() :创建继承自db.Model的所有表
    • 其他:
      • db.session.rollback() 回滚
      • db.session.remove() 移除会话
    • 案例: 编写两个模型类, 一个角色模型类, 还有一个用户模型类
      • 关系: 一对多
    • 注意点:
      • 如果想要打印一个对象的时候看到指定的信息, 那么重写__repr__方法
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

#1.设置数据库的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:654321@127.0.0.1:3306/python_data1"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

#2.创建SQLalchemy对象,关联app
db = SQLAlchemy(app)

#3.编写模型类
#角色(一方)
class Role(db.Model):
    __tablename__ = "roles"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))

    #为了打印一个对象时,显示的结果更加清晰明确:如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
    def __repr__(self):
        return "<Role:%s>"%self.name

#用户(多方)
class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))

    #建立外键
    role_id = db.Column(db.Integer,db.ForeignKey(Role.id))

    #如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
    def __repr__(self):
        return "<User:%s>"%self.name

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

    return "helloworld"

if __name__ == '__main__':
    
    #db.drop_all()
    db.create_all()

    app.run(debug=True)

terminal下,进入ipython3:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
注意:上面图片中User.query中的User是类名,即转化为数据库的一个数据表。也就是说这个User是根据你要在哪个数据表中查找就替换成对应的类名的…

基本查询

在实际工作中,查询操作是最常用到的。

  • 全部都是通过模型类.query来进行的
  • 常见的12条查询语句:
    • 查询所有用户数据 User.query.all()
    • 查询有多少个用户 User.query.count()
    • 查询第1个用户 User.query.first()
    • 查询id为4的用户[3种方式] User.query.get(4)User.query.filter(User.id == 4).first()(这里id是主键,所以结果集中仅有一条结果,用first()取出即可)、User.query.filter_by(id=4).first()
    • 查询名字结尾/开始/包含字符为g的所有数据 User.query.filter(User.name.endswith('g')).all() / User.query.filter(User.name.startswith('g')).all() / User.query.filter(User.name.contains('g')).all()
    • 查询名字不等于wang的所有数据[2种方式] User.query.filter(User.name != 'wang').all()、(略-不需要掌握)
    • 查询名字和邮箱都以 li 开头的所有数据[2种方式] User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all()、(略-不需要掌握)
    • 查询password是 123456 或者 email 以 itheima.com 结尾的所有数据
      在这里插入图片描述
    • 查询id为 [1, 3, 5, 7, 9] 的用户列表 User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()
    • 查询name为liu的角色数据 user = User.query.filter(User.name == 'liu').first() + Role.query.filter(Role.id == user.role_id).first()
    • 查询所有用户数据,并以邮箱升序/降序排序 User.query.order_by(User.email).all() / User.query.order_by(User.email.desc()).all()
    • 每页3个,查询第2页的数据:
      在这里插入图片描述
      在这里插入图片描述

paginate(page,per_page,Error_out):
参数page:表示要查询的页数
参数per_page:表示每页有多少条数据
参数Error_out:建议写成False,这使得查不到不会报错


paginate.pages #总页数
paginate.page #当前页
paginate.items #当前的对象列表

上面查询语句用到的具体代码是:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 1.设置数据库的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:654321@127.0.0.1:3306/python_data1"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_ECHO"] = True

# 2.创建SQLalchemy对象,关联app
db = SQLAlchemy(app)

# 3.编写模型类
# 角色(一方)
class Role(db.Model):
    __tablename__ = "roles"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))

    # 给Role添加了一个users属性, 那么查询的方式是, role.users——角色为role的所有用户
    # 给User添加了一个role属性, 那么查询的方式是, user.role——user的角色
    users = db.relationship("User",backref="role",lazy="dynamic")

    # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
    def __repr__(self):
        return "<Role:%s>"%self.name


# 用户(多方)
class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))
    email = db.Column(db.String(32))
    password = db.Column(db.String(32))

    # 建立外键
    role_id = db.Column(db.Integer,db.ForeignKey(Role.id))

    # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
    def __repr__(self):
        return "<User:%s,%s,%s,%s>"%(self.id,self.name,self.email,self.password)


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

    return "helloworld"


if __name__ == '__main__':

    # 为了演示方便,先删除表,后创建
    # db.drop_all()
    db.create_all()

    # 创建测试数据
    ro1 = Role(name='admin')
    db.session.add(ro1)
    db.session.commit()

    # 再次插入一条数据
    ro2 = Role(name='user')
    db.session.add(ro2)
    db.session.commit()

    # 多条用户数据
    us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id)
    us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id)
    us5 = User(name='tang', email='tang@itheima.com', password='158104', role_id=ro2.id)
    us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id)
    us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id)
    us8 = User(name='liu', email='liu@itheima.com', password='867322', role_id=ro1.id)
    us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id)
    us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id)
    db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
    db.session.commit()

    app.run(debug=True)

注意:如果对代码进行了修改,就要重新在ipython3中导入:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

补充:
在这里插入图片描述

数据库关系查询relationship
  • 解释: 为了方便数据库的关联查询

  • 特点:

    • 1.不会在数据库产生实体字段,仅仅是为了方便开发者查询
    • 2.关系属性,需要在一方添加
    • 3.外键是添加在一方的, 并且关系属性的使用需要依赖于外键
  • 示例:

    • 1.如果知道了角色的情况下,能否快速查询出,哪些用户扮演了该角色

      • 原始查询方法:
        • role = Role.query.get(1)
        • users = User.query.filter(User.role_id == role.id).all()
      • 快速查询:
        • 使用relationship添加关系属性,就可以快速查询了.
        • 格式:
          • users = db.relationship(“多方的模型类”)
        • 使用格式:
          • role = Role.query.get(1)
          • users = role.users

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据库反向查询backref
  • 解释:如果知道了用户的情况下,能否快速查询出,该用户扮演了哪个角色
  • 原始查询方法:
    • user = User.query.get(1)
    • role = Role.querye.filter(Role.id == user.role_id).first()
  • 快速查询:
    • 使用backref添加反向属性,就可以快速查询了
    • 格式:
      • users = db.relationship(“多方的模型类”,backref=“role”)
    • 快速查询:
      • user = User.query.get(1)
      • role = user.role

在这里插入图片描述
user = User.query.get(1)
role = user.role # 这里的role是上图红框内backref的值

在这里插入图片描述

数据库懒查询lazy
  • 解释: 一旦使用了relationship,backref,那么系统会默认做子查询,这会使得效率较低。为了避免“多此一举”,设置懒查询,使其成为了动态查询。
    • 子查询(subquery): 查询出了一方, 就会自动的将关联的一方查询出来
    • 动态查询(dynamic): 只有用到了才去查询
  • lazy使用
    • db.relationship(“多方的模型类”,backref=“role”,lazy=“dynamic”)

对比数据库关系查询relationship这一知识点中的截图,可以看到,执行role = Role.query.get(1) + role.users后有输出结果,而这里并没有:
在这里插入图片描述
上图黄框内表示结果集,所以如果想让这个结果集中的结果输出,就需要另外的步骤了。

综合案例-图书管理

分析图书馆案例实现流程
  • 1.数据库配置
    • 作者模型(一方)
    • 书籍模型(多方)
# 1 数据库配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:654321@127.0.0.1:3306/py_library"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False


# 2 创建SQLAlchemy对象,关联app
db = SQLAlchemy(app)


# 3 编写模型类
# 3.1 作者(一方)
class Author(db.Model):
    __tablename__ = "authors"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    # 关系属性(因为后面我们可能想查询某个作者都写了哪些书,所以下面设置books,这样之后author.books就是结果了)
    books = db.relationship("Book", backref="author")


# 3.2 书籍(多方)
class Book(db.Model):
    __tablename__ = "books"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    # 外键
    author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
    # 上行语句等价于: author_id = db.Column(db.Integer, db.ForeignKey("authors.id"))
  • 2.添加测试数据
  • 3.实现添加功能(添加作者&添加书籍)
  • 4.实现删除功能(删除作者&删除书籍)
图书馆测试数据添加[掌握]
if __name__ == "__main__":
    db.drop_all()
    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(debug=True)
图书馆测试数据显示[掌握]
  • 步骤
    • 1.查询所有作者信息
    • 2.携带作者信息,渲染页面
# 4 展示页面
@app.route('/')
def quickflask():
    # 4.1 查询所有的作者信息
    authors = Author.query.all()
    # 4.2 携带作者信息,渲染页面
    return render_template("t1.html", authors=authors)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {# 添加书籍 #}
    <form action="" method="post">
        作者:<input type="text" name="author"><br>
        书籍:<input type="text" name="book"><br>
        <input type="submit" value="添加">
    </form>

    <hr>

    {# 遍历数据 #}
    <ul>
        {% for author in authors %}
            <li>作者:{{ author.name }}</li>
            <ul>
                {% for book in author.books %}
                    <li>书籍:{{ book.name }}</li>
                {% endfor %}
            </ul>
        {% endfor %}
    </ul>
</body>
</html>

注意:html文件里的内容下面会进行更新。

图书馆添加数据[掌握]
  • 添加的逻辑分析:
    • 0.如果输入内容有空值, 不能添加
    • 1.如果作者存在,书籍存在, 不能添加
    • 2.如果作者存在,书籍不存在, 可以添加
    • 3.如果作者不存在, 可以添加

碎碎念:这里flask web实现的逻辑,令我不由得感叹,“牛啊”。果然“人生苦短,我用python”。。。同时觉得老师讲的真的逻辑无比清晰。赞。开发一种新的语言的人很牛,开发广受欢迎的编译器(能给开发人员带来很多方便)的人也很牛呀。

# 5 添加书籍&作者
@app.route('/add_data', methods=["post"])
def add_data():
    # 5.1 获取提交的数据
    author_name = request.form.get("author")  # "author"是引用的html文件中action为add_data的表单中的name属性值,对应的是input标签,所以这里就是获取用户输入的内容
    book_name = request.form.get("book")

    # 判断是否有空值
    if not all([author_name, book_name]):
        flash("输入信息不完整!")
        return redirect("/")

    # 5.2 根据作者的信息查询作者对象
    author = Author.query.filter(Author.name == author_name).first()
    # 5.3 判断作者是否存在
    if author:  # 作者存在
        # 5.4 判断要添加的书籍是否已经存在
        book = Book.query.filter(Book.name == book_name, Book.author_id == author.id).first()
        if book:  # 书籍存在
            flash("书籍已存在,无需再添加!")
        else:  # 书籍不存在:创建书籍对象
            book = Book(name=book_name, author_id=author.id)
            db.session.add(book)
            db.session.commit()
    else:  # 作者不存在:创建作者对象+创建书籍对象
        author = Author(name=author_name)
        db.session.add(author)
        db.session.commit()
        book = Book(name=book_name, author_id=author.id)
        db.session.add(book)
        db.session.commit()
    # 5.5 重定向到首页展示
    return redirect("/")
图书馆删除书籍[掌握]
  • 步骤
    • 1.根据书籍编号获取书籍对象
    • 2.删除书籍对象
    • 3.重定向到页面展示
# 6 删除书籍
@app.route('/del_book/<int:book_id>')
def del_book(book_id):
    # 6.1 根据书籍ID取出书籍对象
    book = Book.query.get(book_id)
    # 6.2 删除书籍
    db.session.delete(book)
    db.session.commit()
    # 6.3 重定向到页面展示
    return redirect("/")
图书馆删除作者[掌握]
  • 步骤
    • 1.根据作者编号获取作者对象
    • 2.遍历删除,作者书籍对象
    • 3.删除作者,提交数据库
    • 4.重定向到页面展示
# 7 删除作者
@app.route('/del_author/<int:author_id>')
def del_author(author_id):
    # 7.1 根据作者ID获取作者对象
    author = Author.query.get(author_id)
    # 7.2 遍历该作者的所有书籍,并删除
    for book in author.books:
        db.session.delete(book)
    # 7.3 删除作者
    db.session.delete(author)
    # 7.4 将以上更改提交到数据库
    db.session.commit()
    # 7.4 重定向到展示页面
    return redirect("/")
图书馆CSRFProtect应用[掌握]
  • 作用: 防止csrf攻击的[项目倒数第二天看源代码校验过程]
  • 使用步骤:
    • 1.导入类CSRFProtect
    • 2.使用CSRFProtect保护app
      • 一旦使用POST,PUT,DELTE,PATCH方式提交的时候就需要校验csrf_token,所以需要设置csrf_token到表单中,否则会出现Bad Request的错误。
    • 3.需要设置SECRET_KEY,用来加密csrf_token
    • 4.设置csrf_token到表单中

在这里插入图片描述
在这里插入图片描述

最终代码&效果

只有html文件有更新,其他内容都已经在上面展示出来了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {# 添加书籍 #}
    {# action:提交到的路由地址 method:提交的方式 #}
    <form action="/add_data" method="post">
        {# 设置隐藏字段:csrf_token #}
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        作者:<input type="text" name="author"><br>
        书籍:<input type="text" name="book"><br>
        <input type="submit" value="添加"><br>

        {# 遍历flash()方法存储的消息(列表) #}
        {% for message in get_flashed_messages() %}
            <span style="color: red;">{{ message }}</span>
        {% endfor %}
    </form>

    <hr>

    {# 遍历数据 #}
    <ul>
        {% for author in authors %}
            {# <li>作者:{{ author.name }} <a href="/del_author/{{ author.id }}">删除</a></li> #}
            {# 上行语句可写成: #}
            <li>作者:{{ author.name }} <a href="{{ url_for("del_author", author_id=author.id) }}">删除</a></li>
            <ul>
                {% for book in author.books %}
                    <li>书籍:{{ book.name }} <a href="/del_book/{{ book.id }}">删除</a></li>
                {% endfor %}
            </ul>
        {% endfor %}
    </ul>
</body>
</html>

在这里插入图片描述

多对多演练

表结构多对多分析[掌握]
  • 解释: 多对多的关系,一般会被拆分成两张一对多的表。
表结构多对多代码演练[掌握]

下面以学生表、课程表进行演练。

  • 中间表:
  tb_student_course = db.Table(
      "tb_student_course",
  	db.Column("student_id",db.Integer,db.Foreign("students.id"))
      db.Column("courses_id",db.Integer,db.Foreign("courses.id"))
  )
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

# 1 设置app的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:654321@localhost:3306/many2many"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 2 创建SQLAlchemy对象,关联app
db = SQLAlchemy(app)

# 3 编写模型类
# 中间表
tb_student_course = db.Table(
    "tb_student_course",
    db.Column("student_id", db.Integer, db.ForeignKey("students.id")),
    db.Column("course_id", db.Integer, db.ForeignKey("courses.id"))
)

# 学生
class Student(db.Model):
    __tablename__ = "students"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32))

    # 关系属性secondary: 使用在多对多中,用来表示二次查询的
    courses = db.relationship("Course", backref="students", secondary="tb_student_course")

    # 为了方便输出对象查看,重写__repr__方法
    def __repr__(self):
        return "<Student:%s>"%self.name

# 课程
class Course(db.Model):
    __tablename__ = "courses"
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(32))

    # 为了方便输出对象查看,重写__repr__方法
    def __repr__(self):
        return "<Student:%s>"%self.name


@app.route('/')
def quickflask():
    return 'hello'


if __name__ == '__main__':
    db.drop_all()
    db.create_all()

    # 添加测试数据
    stu1 = Student(name='张三')
    stu2 = Student(name='李四')
    stu3 = Student(name='王五')

    cou1 = Course(name='物理')
    cou2 = Course(name='化学')
    cou3 = Course(name='生物')

    stu1.courses = [cou2, cou3]
    stu2.courses = [cou2]
    stu3.courses = [cou1, cou2, cou3]

    db.session.add_all([stu1, stu2, stu2])
    db.session.add_all([cou1, cou2, cou3])

    db.session.commit()

    app.run(debug=True)

常见关系模板代码

一对多
多对多
自关联一对多(了解)
自关联多对多(了解)

数据库迁移

  • 目的: 当数据库的表结构发生变化之后,如果直接删除原有的数据,再添加新的数据,有可能导致数据丢失
  • 注意点:
    • 1.是为了备份表结构,而不是数据
    • 2.如果想要备份数据,需要使用工具navicat,mysqlworkbench,等等
    • 3.更新的过程数据一般不会丢失,做降级的时候需要谨慎操作,因为降级会导致数据丢失
  • 操作流程:
    • 1.安装扩展
      • pip install flask_script
      • pip install flask_migrate
    • 2.导入三个类
      • from flask_script import Manager
      • from flask_migrate import Migrate, MigrateCommand
    • 3.通过Manager类创建对象manager,管理app
      • manager = Manager(app)
    • 4.使用Migrate关联db,app
      • Migrate(app,db)
    • 5.给manager添加一条操作命令
      • manager.add_command(“db”,MigrateCommand)
    • 相关迁移命令:
      • 生成迁移文件夹[一次就好] python xxx.py db init
      • 将模型类生成迁移脚本[重复执行] python xxx.py db migrate -m '注释'
      • 将迁移脚本更新到数据库中[重复执行] python xxx.py db upgrade/downgrade [version]
      • 其他命令
        • 查看最新版本的命令 python xxx.py db show
        • 查看当前版本 python xxx.py db current
        • 查看所有的历史版本 python xxx.py db history
from flask import Flask
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from flask_sqlalchemy import SQLAlchemy, BaseQuery

app = Flask(__name__)

# 设置数据库配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@localhost:3306/data39"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 创建SQLAlchemy对象,关联app
db = SQLAlchemy(app)

# 3.通过Manager类创建对象manager,管理app
manager = Manager(app)

# 4.使用Migrate,关联db,app
Migrate(app,db)

# 5.给manager添加一条操作命令
manager.add_command("db",MigrateCommand)

# 6.编写模型类
class Student(db.Model):
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))
    age = db.Column(db.Integer)


@app.route('/')
def hello_world():
    return "helloworld"

if __name__ == '__main__':
	# 7.
    manager.run()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值