目錄
一、什么是ORM
- ORM 全拼
Object-Relation Mapping
. 稱為對象-關系映射 - 主要實現模型對象到關系數據庫數據的映射.
- 比如:把數據庫表中每條記錄映射為一個模型對象
關系映射
二、Flask-SQLAlchemy安裝及設置
1. 安裝
- 安裝 flask-sqlalchemy
pip install flask-sqlalchemy
- 如果連接的是 mysql 數據庫,需要安裝 mysqldb
pip install flask-mysqldb
提示: 如果flask-mysqldb安裝不上,推薦安裝, pip install pymysql
2. 數據庫連接設置
- 設置數據庫的鏈接地址,追蹤信息
- 格式:mysql://<用戶名>:<密碼>@:<端口>/數據庫名稱
# 數據庫鏈接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
# 動態追蹤修改設置,如未設置只會提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
查看映射的sql語句,設置: app.config['SQLALCHEMY_ECHO'] = True
- 配置完成需要去 MySQL 中創建項目所使用的數據庫
$ mysql -uroot -pmysql
$ create database test charset utf8;
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#2.設置數據庫的配置信息
#設置數據庫的鏈接信息,
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
#該字段增加了大量的開銷,會被禁用,建議設置為False
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
#3.創建sqlalchemy對象db,關聯app
db = SQLAlchemy(app)
# 4.編寫模型類,字段,繼承自db.Model
class Student(db.Model):
__tablename__ = "students"
#主鍵, 參數1: 表示id的類型, 參數2: 表示id的約束類型
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(32))
@app.route('/')
def hello_world():
return "helloworld"
if __name__ == '__main__':
#刪除繼承自db.Model的表
db.drop_all()
#5.創建數據庫的表,創建的是繼承自db.Model的表
db.create_all()
app.run(debug=True)
三、數據庫基本操作
- 在Flask-SQLAlchemy中,插入、修改、刪除操作,均由數據庫會話管理。
- 會話用 db.session 表示。在准備把數據寫入數據庫前,要先將數據添加到會話中然后調用 db.session.commit() 方法提交會話。
- 在 Flask-SQLAlchemy 中,查詢操作是通過 query 對象操作數據。
- 最基本的查詢是返回表中所有數據,可以通過過濾器進行更精確的數據庫查詢。
1. 增刪改
"""
增刪改
- 全部都是使用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() 移除會話
- 案例: 編寫兩個模型類, 一個角色模型類, 還有一個用戶模型類
- 關系: 一對多
"""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#1.設置數據庫的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
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)
使用ipython進行測試,前提是先進行安裝
增
改
刪
2. 查詢
# -*- coding = utf-8 -*-
# @Time : 2020/10/2 10:15
# @Author : md
'''
查詢練習
'''
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 1.設置數據庫的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
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
# 給user添加了一個role屬性, 那么查詢的方式是, user.role
# 重點 建立關系,這里的名字為想要建立關系的模型名字
# 解釋:前半句話是給Role(本模型)模型添加一個users屬性,因為這兩個數據庫通外鍵連接
# 所以,可以通過這個表的對象,就可以訪問User表中的數據,例如:查看角色是admin的所有用戶role.users
# 后半句是給本(自己)模型添加一個role屬性,這樣User表中的對象,就可以訪問本表中的數據,可以知道某個用戶是什么身份
# 例如查看用戶的身份,user.role
# lazy="dynamic" 是懶加載
# backref反向引用
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)
- 其中realtionship描述了Role和User的關系。
- 第一個參數為對應參照的類"User"
- 第二個參數backref為類User,反向引用屬性
第三個參數lazy決定了什么時候SQLALchemy從數據庫中加載數據
- 如果設置為子查詢方式(subquery),則會在加載完Role對象后,就立即加載與其關聯的對象,這樣會讓總查詢數量減少,但如果返回的條目數量很多,就會比較慢
-
- 設置為 subquery 的話,role.users 返回所有數據列表
- 另外,也可以設置為動態方式(dynamic),這樣關聯對象會在被使用的時候再進行加載,並且在返回前進行過濾,如果返回的對象數很多,或者未來會變得很多,那最好采用這種方式
User.query.filter().all()
3. 查詢練習
查詢所有用戶數據
User.query.filter().all()
此時過濾器可以不寫
User.query.all()
查詢有多少個用戶
User.query.count()
查詢第1個用戶
User.query.first()
查詢id為4的用戶[3種方式]
User.query.get(4) 此時get里面是主鍵
User.query.filter(User.id == 4).all() 返回的是列表,但滿足的只有一個
User.query.filter(User.id == 4).first()
User.query.filter_by(id=4).first()
查詢名字結尾字符為g的所有數據[開始/結尾/包含]
User.query.filter(User.name.startswith('g')).all()
User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.name.contains('g')).all()
查詢名字不等於wang的所有數據
User.query.filter(User.name != 'wang').all()
查詢名字和郵箱都以 li 開頭的所有數據
User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()
查詢password是 123456 或者 email 以 itheima.com 結尾的所有數據
from sqlalchemy import or_
User.query.filter(or_(User.password == '123456',User.email.endswith('itheima.com'))).all()
查詢id為 [1, 3, 5, 7, 9] 的用戶列表
User.query.filter(User.id.in_([1,3,5,7,9])).all()
查詢name為liu, 的角色數據
user = User.name.filter(User.name == 'liu').first()
role = 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頁的數據
#page: 表示要查詢的頁數
#per_page: 表示每頁有多少條數據
#Error_out: 建議寫成False,查不到不會報錯
paginate = User.query.paginate(page,per_page,Error_out)
paginate.pages #總頁數
paginate.page #當前頁
paginate.items #當前的對象列表
查詢前兩條數據
User.query.limit(2).all()
lazy="dynamic"
四、綜合案例-圖書管理
目的:
- 表單創建
- 數據庫操作
- 一對多關系演練
實現步驟:
- 1.創建數據庫配置信息,定義模型類
- 2.創建數據庫表,添加測試數據
- 3.編寫html頁面,展示數據
- 4.添加數據
- 5.刪除書籍,刪除作者
1. 圖書館測試數據顯示
- 步驟
- 1.查詢所有作者信息
- 2.攜帶作者信息,渲染頁面
2. 圖書館添加數據
- 添加的邏輯分析:
- 1.如果作者存在,書籍存在, 不能添加
- 2.如果作者存在,書籍不存在,可以添加
- 3.如果作者不存在,可以添加
3. 圖書館刪除書籍
- 步驟
- 1.根據書籍編號獲取書籍對象
- 2.刪除書籍對象
- 3.重定向到頁面展示
4. 圖書館刪除作者
- 步驟
- 1.根據作者編號獲取作者對象
- 2.遍歷刪除,作者書籍對象
- 3.刪除作者,提交數據庫
- 4.重定向到頁面展示
5. 圖書館CSRFProtect應用
- 作用: 防止csrf攻擊的
- 使用步驟:
- 1.導入類CSRFProtect
- 2.使用CSRFProtect保護app
- 一旦使用POST,PUT,DELTE,PATCH方式提交的時候就需要校驗csrf_token
- 3.需要設置SECRET_KEY,用來加密csrf_token
- 4.設置csrf_token到表單中
6. 表單的創建
# -*- coding = utf-8 -*-
# @Time : 2020/10/2 16:07
# @Author : md
from flask import Flask, render_template, request, redirect, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
# 由於使用了flash,所以得設置
app.config["SECRET_KEY"] = "wepricsjf"
# 使用 CSRFProtect保護app
CSRFProtect(app)
# 1.設置數據庫的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 生成對應的sql語句在控制台
# app.config["SQLALCHEMY_ECHO"] = True
# 2.創建SQLalchemy對象,關聯app
db = SQLAlchemy(app)
# 3.編寫模型類
# 作者(一方)
class Author(db.Model):
__tablename__ = "authors"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
# 關系數據,必須有外鍵為基礎
books = db.relationship("Book", backref="author")
# 如果一個類繼承自object那么重寫__str__方法即可, 如果是繼承自db.Model那么需要重寫__repr__方法
def __repr__(self):
return "<Author:%s>" % self.name
# 書籍(多方)
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))
# 如果一個類繼承自object那么重寫__str__方法即可, 如果是繼承自db.Model那么需要重寫__repr__方法
def __repr__(self):
return "<Book:%s,%s>" % (self.id, self.name)
# 5. 展示數據
@app.route('/')
def hello_world():
# 1. 查詢所有的作者信息,因為作者有外鍵,可以通過關系數據方便的查出該作者對應的書籍
authors = Author.query.all()
return render_template("library.html", authors=authors)
# 6. 添加數據
@app.route("/add_data", methods=["POST"])
def add_data():
# 1. 獲取提交的數據
author_name = request.form.get("author")
book_name = request.form.get("book")
# 先判斷輸入的內容是否為空
if not all([author_name, book_name]):
flash("作者或書籍不能為空")
return redirect("/")
# 2. 根據作者信息查詢作者對象
author = Author.query.filter(Author.name == author_name).first()
# 3. 判斷作者是否存在
if author:
# 4. 通過書籍名稱查詢書籍對象,並且這本書的作者的id和查詢出來的作者的id一樣
# 也就是查看要添加的這本書是不是該作者寫的
book = Book.query.filter(Book.name == book_name, Book.author_id == Author.id).first()
# 5. 判斷書籍是否存在
if book:
# return "該作者已經寫了這本書了"
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()
# 6. 重定向到首頁
return redirect("/")
# 7. 刪除書籍
@app.route("/delete_book/<int:book_id>")
def delete_book(book_id):
# 1. 根據id獲取到書籍對象
book = Book.query.get(book_id)
# 2. 刪除這個書籍
db.session.delete(book)
db.session.commit()
# 3. 重定向到頁面
return redirect("/")
# 7. 刪除作者
@app.route("/delete_author/<int:author_id>")
def delete_author(author_id):
# 1. 根據id獲取到作者對象
author = Author.query.get(author_id)
# 2. 這個作者的全部書籍,由於使用了關系數據,直接這樣寫就可以
books = author.books
# 3. 遍歷這個作者的全部書籍
for book in books:
db.session.delete(book)
# 4. 刪除作者
db.session.delete(author)
db.session.commit()
# 5. 重定向到頁面
return redirect("/")
if __name__ == '__main__':
# 為了演示方便,先刪除后創建
db.drop_all()
db.create_all()
# 4. 添加測試數據庫
# 生成數據
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()
7. library.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 , 只要使用了CSRFProtect,然后使用模板渲染的時候就可以直接使用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>
{% for message in get_flashed_messages() %}
<span style="color: red;">{{ message }}</span>
{% endfor %}
</form>
<hr>
{# 數據展示 #}
<ul>
{# 遍歷作者 #}
{% for author in authors %}
{# <li>作者: {{ author.name }}</li>#}
{# <li>作者: {{ author.name }} <a href="/delete_author/{{ author.id }}">刪除</a></li>#}
<li>作者: {{ author.name }} <a href="{{ url_for("delete_author",author_id=author.id) }}">刪除</a></li>
{# 遍歷作者的書籍 #}
<ul>
{% for book in author.books %}
{# <li>書籍: {{ book.name }} </li>#}
<li>書籍: {{ book.name }} <a href="/delete_book/{{ book.id }}">刪除</a></li>
{% endfor %}
</ul>
{% endfor %}
</ul>
</body>
</html>
五、多對多
在項目開發過程中,會遇到很多數據之間多對多關系的情況,比如:
- 學生網上選課(學生和課程)
- 老師與其授課的班級(老師和班級)
- 用戶與其收藏的新聞(用戶和新聞)
- 等等...
所以在開發過程中需要使用 ORM 模型將表與表的多對多關聯關系使用代碼描述出來。多對多關系描述有一個唯一的點就是:需要添加一張單獨的表去記錄兩張表之間的對應關系
1. 需求分析
- 學生可以網上選課,學生有多個,課程也有多個
- 學生有:張三、李四、王五
- 課程有:物理、化學、生物
- 選修關系有:
-
- 張三選修了化學和生物
- 李四選修了化學
- 王五選修了物理、化學和生物
需求:
- 查詢某個學生選修了哪些課程
- 查詢某個課程都有哪些學生選擇
2. 代碼
# -*- coding = utf-8 -*-
# @Time : 2020/10/2 19:30
# @Author : md
'''
多對多,學生和課程
'''
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 1.設置數據庫的配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# app.config["SQLALCHEMY_ECHO"] = True
# 2.創建SQLalchemy對象,關聯app
db = SQLAlchemy(app)
# 3.編寫模型類
# 學生
class Student(db.Model):
__tablename__ = "students"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
# 關系數據,使用在多對多中的時候注意secondary這個屬性,是中間表的表名,用來二次查詢
courses = db.relationship("Course", backref="students", secondary="td_student_course")
# 如果一個類繼承自object那么重寫__str__方法即可, 如果是繼承自db.Model那么需要重寫__repr__方法
def __repr__(self):
return "<Role:%s>" % self.name
# 課程
class Course(db.Model):
__tablename__ = "courses"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
# 如果一個類繼承自object那么重寫__str__方法即可, 如果是繼承自db.Model那么需要重寫__repr__方法
def __repr__(self):
return "<User:%s>" % self.name
# 中間表
db.Table(
"td_student_course",
db.Column("student_id", db.Integer, db.ForeignKey(Student.id)),
db.Column("course_id", db.Integer, db.ForeignKey(Course.id))
)
@app.route('/')
def hello_world():
return "helloworld"
# 為了演示,先刪除后創建
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()
if __name__ == '__main__':
app.run()
六、數據庫遷移
- 目的: 當數據庫的表結構發生變化之后,如果直接刪除原有的數據,再添加新的數據,有可能導致數據丟失
- 注意點:
- 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.安裝擴展
# -*- coding = utf-8 -*-
# @Time : 2020/10/2 20:38
# @Author : md
from flask import Flask
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 設置數據庫配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@localhost:3306/test1"
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)
# email = db.Column(db.String(32))
@app.route('/')
def hello_world():
return "helloworld"
if __name__ == '__main__':
manager.run()
生成遷移文件夾
將模型類生成遷移腳本
將遷移腳本更新到數據庫中
此時就可以在數據庫中看到對應的表了
此時在代碼中多寫一行,添加一列
然后繼續執行這兩條命令,就會看到數據表結構中就多了一列
還可以進行降級
然后再升級到指定的版本