数据库
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.操作数据库
- 增删改
- 查询
- 1.安装扩展
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)
在运行系项目之前,需要手动创建所需数据库。创建完之后运行该项目,该项目的代码最终会帮助我们在这个库中创建出数据表。
运行项目。
检查:
需要注意到的:
- 因为SQLALChemy去app身上读取了配置信息,所以需要设置到app.config身上
- 数据库的链接信息
- 如果安装的是flask_mysqldb, 那么链接信息: mysql://<用户名>:<密码>@<ip地址>:<端口号>/<数据库名字>
- 如果安装的是pymysql, 那么链接信息: mysql+pymysql://<用户名>:<密码>@<ip地址>:<端口号>/<数据库名字>
- 编写的模型类必须继承自db.Model才能被映射
- 如果不指定表名称,默认生成的就是模型类的小写,如果需要自己指定表名使用__tablename__=‘表名’
- 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
- 查看最新版本的命令
- 生成迁移文件夹[一次就好]
- 1.安装扩展
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()