1. 程式人生 > 程式設計 >flask 擴充套件(一)

flask 擴充套件(一)

Flask-Script 擴充套件命令列

from flask import Flask
from flask_script import Manager

app = Flask(__name__)

manager = Manager(app)


@app.route('/')
def index():
    return '我的快樂時代'


if __name__ == "__main__":
    manager.run()
複製程式碼

通過使用Flask-Script擴充套件,我們可以在Flask伺服器啟動的時候,通過命令列的方式傳入引數。而不僅僅通過app.run()方法中傳參,

比如我們可以通過python hello.py runserver --host ip地址,告訴伺服器在哪個網路介面監聽來自客戶端的連線。預設情況下,伺服器只監聽來自伺服器所在計算機發起的連線,即localhost連線。

我們可以通過 python hello.py runserver --help 來檢視引數:

Flask-WTF

相關參考連結

github.com/luhuisicnu/…

關於 web 表單

web表單是web應用程式的基本功能。 它是HTML頁面中負責資料採集的部件。表單有三個部分組成:表單標籤、表單域、表單按鈕。表單允許使用者輸入資料,負責HTML頁面資料採集,通過表單將使用者輸入的資料提交給伺服器。

在Flask中,為了處理web表單,我們一般使用Flask-WTF擴充套件,它封裝了WTForms,並且它有驗證表單資料的功能。

WTForms支援的HTML標準欄位

WTForms常用驗證函式

表單中的 CSRF

使用Flask-WTF需要配置引數SECRET_KEY。 CSRF_ENABLED是為了CSRF(跨站請求偽造)保護。 SECRET_KEY用來生成加密令牌,當CSRF啟用的時候,該設定會根據設定的密匙生成加密令牌。

在HTML頁面中直接寫form表單的模式

檔案結構:

templates/login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form method='post'>
        <input type="text" name="username" placeholder='Username'>
        <input type="password" name="password" placeholder='password'>
        <input type="submit">
    </form>
</body>
</html>
複製程式碼

hello.py

from flask import Flask,request,render_template

app = Flask(__name__)


@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        print(username,password)

    return render_template('login.html',method=request.method)


if __name__ == "__main__":
    app.run()
複製程式碼

使用Flask-WTF實現表單

安裝:

pip install flask-wtf
複製程式碼

首先需要配置引數: app.config['SECRET_KEY'] = 'ruiyang'

檔案結構:

hello.py

from flask import Flask,render_template,redirect,url_for,flash

from flask_wtf import Form
from wtforms import SubmitField,StringField,PasswordField
from wtforms.validators import DataRequired,EqualTo

app = Flask(__name__)
app.config['SECRET_KEY'] = 'ruiyang'


class Login(Form):
    us = StringField(label=u'使用者:',validators=[DataRequired()])
    ps = PasswordField(label=u'密碼',validators=[DataRequired(),EqualTo('ps2','err')])
    ps2 = PasswordField(label=u'確認密碼',validators=[DataRequired()])
    submit = SubmitField(u'提交')


@app.route('/','POST'])
def index():
    form = Login()
    if form.validate_on_submit():
        name = form.us.data
        pswd = form.ps.data
        pswd2 = form.ps2.data
        print(name,pswd,pswd2)
        return "login seccess"
    else:
        if request.method == 'POST':
            flash(u'資訊有誤,請重新輸入!')
        print(form.validate_on_submit())

    return render_template('login.html',form=form)


if __name__ == '__main__':
    app.run(debug=True)
複製程式碼

templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form method="post">
            {{ form.csrf_token() }}
            {{ form.us.label }}
            <p>{{ form.us }}</p>
            {{ form.ps.label }}
            <p>{{ form.ps }}</p>
            {{ form.ps2.label }}
            <p>{{ form.ps2 }}</p>
            <p>{{ form.submit() }}</p>
            {% for x in get_flashed_messages() %}
                {{ x }}
            {% endfor %}
     </form>
</body>
</html>
複製程式碼

flask-sqlalchemy

相關參考連結

github.com/luhuisicnu/…

安裝

pip install flask-sqlalchemy
複製程式碼

需要連線mysql資料庫,仍然需要安裝 flask-mysqldb

pip install flask-mysqldb
複製程式碼

配置

Flask的資料庫設定:

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test'
複製程式碼

常用的SQLAlchemy欄位型別

常用的SQLAlchemy列選項

常用的SQLAlchemy關係選項

在程式中的基礎操作

建立測試資料:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)

# 設定連線資料庫的URL
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test'
# 設定每次請求結束後會自動提交資料庫中的改動
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 查詢時會顯示原始SQL語句
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(64),unique=True)
    us = db.relationship('User',backref='role')

    def __repr__(self):
        return 'Role:{}'.format(self.name)


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer,unique=True,index=True)
    email = db.Column(db.String(64),unique=True)
    pswd = db.Column(db.String(64))
    role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:{}'.format(self.name)


if __name__ == '__main__':
    db.drop_all()
    db.create_all()
    ro1 = Role(name='admin')
    ro2 = Role(name='user')
    db.session.add_all([ro1,ro2])
    db.session.commit()
    us1 = User(name='wang',email='[email protected]',pswd='123456',role_id=ro1.id)
    us2 = User(name='zhang',email='[email protected]',pswd='201512',role_id=ro2.id)
    us3 = User(name='chen',email='[email protected]',pswd='987654',role_id=ro2.id)
    us4 = User(name='zhou',email='[email protected]',pswd='456789',role_id=ro1.id)
    db.session.add_all([us1,us2,us3,us4])
    db.session.commit()
    app.run(debug=True)
複製程式碼

執行程式之後啟動 flask shell 進行操作:

建立和刪除表:

>>> db.create_all()
2019-08-10 13:45:02,631 INFO sqlalchemy.engine.base.Engine DESCRIBE `roles`
2019-08-10 13:45:02,631 INFO sqlalchemy.engine.base.Engine ()
2019-08-10 13:45:02,632 INFO sqlalchemy.engine.base.Engine DESCRIBE `users`
2019-08-10 13:45:02,632 INFO sqlalchemy.engine.base.Engine ()
>>> db.drop_all()
2019-08-10 13:45:11,267 INFO sqlalchemy.engine.base.Engine DESCRIBE `roles`
2019-08-10 13:45:11,267 INFO sqlalchemy.engine.base.Engine ()
2019-08-10 13:45:11,268 INFO sqlalchemy.engine.base.Engine DESCRIBE `users`
2019-08-10 13:45:11,268 INFO sqlalchemy.engine.base.Engine ()
2019-08-10 13:45:11,270 INFO sqlalchemy.engine.base.Engine 
DROP TABLE users
2019-08-10 13:45:11,270 INFO sqlalchemy.engine.base.Engine ()
2019-08-10 13:45:11,283 INFO sqlalchemy.engine.base.Engine COMMIT
2019-08-10 13:45:11,284 INFO sqlalchemy.engine.base.Engine 
DROP TABLE roles
2019-08-10 13:45:11,284 INFO sqlalchemy.engine.base.Engine ()
2019-08-10 13:45:11,294 INFO sqlalchemy.engine.base.Engine COMMIT
複製程式碼

插入單條資料:

>>> from hello import Role
>>> role_admin = Role(name="admin") 
>>> db.session.add(role_admin) 
>>> db.session.commit()
2019-08-10 13:46:40,071 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-10 13:46:40,071 INFO sqlalchemy.engine.base.Engine INSERT INTO roles (name) VALUES (%s)
2019-08-10 13:46:40,072 INFO sqlalchemy.engine.base.Engine ('admin',)
2019-08-10 13:46:40,073 INFO sqlalchemy.engine.base.Engine COMMIT
>>> role1 = Role(name="user1") 
>>> db.session.add(role1) 
>>> db.session.commit()
2019-08-10 13:47:03,975 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-10 13:47:03,975 INFO sqlalchemy.engine.base.Engine INSERT INTO roles (name) VALUES (%s)
2019-08-10 13:47:03,975 INFO sqlalchemy.engine.base.Engine ('user1',)
2019-08-10 13:47:03,976 INFO sqlalchemy.engine.base.Engine COMMIT
>>> role2 = Role(name="ruiyang") 
>>> db.session.add(role2) 
>>> db.session.commit()
2019-08-10 13:47:39,205 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-10 13:47:39,205 INFO sqlalchemy.engine.base.Engine INSERT INTO roles (name) VALUES (%s)
2019-08-10 13:47:39,205 INFO sqlalchemy.engine.base.Engine ('ruiyang',)
2019-08-10 13:47:39,206 INFO sqlalchemy.engine.base.Engine COMMIT
複製程式碼

插入多條資料: add_all()

>>> us1 = User(name='wang',role_id=role_admin.id)
2019-08-10 13:49:09,064 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-10 13:49:09,064 INFO sqlalchemy.engine.base.Engine SELECT roles.id AS roles_id,roles.name AS roles_name 
FROM roles 
WHERE roles.id = %s
2019-08-10 13:49:09,065 INFO sqlalchemy.engine.base.Engine (1,)
>>> us2 = User(name='zhang',role_id=role1.id)
2019-08-10 13:49:52,577 INFO sqlalchemy.engine.base.Engine SELECT roles.id AS roles_id,roles.name AS roles_name 
FROM roles 
WHERE roles.id = %s
2019-08-10 13:49:52,577 INFO sqlalchemy.engine.base.Engine (2,)
>>> us3 = User(name='chen',role_id=role1.id)
>>> us4 = User(name='zhou',role_id=role2.id)
2019-08-10 13:50:20,853 INFO sqlalchemy.engine.base.Engine SELECT roles.id AS roles_id,roles.name AS roles_name 
FROM roles 
WHERE roles.id = %s
2019-08-10 13:50:20,853 INFO sqlalchemy.engine.base.Engine (3,)
>>> db.session.add_all([us1,us4])
>>> db.session.commit()
2019-08-10 13:50:38,442 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name,email,role_id) VALUES (%s,%s,%s)
2019-08-10 13:50:38,442 INFO sqlalchemy.engine.base.Engine ('wang','[email protected]','123456',1)
2019-08-10 13:50:38,444 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name,444 INFO sqlalchemy.engine.base.Engine ('zhang','[email protected]','201512',2)
2019-08-10 13:50:38,445 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name,445 INFO sqlalchemy.engine.base.Engine ('chen','[email protected]','987654',446 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name,446 INFO sqlalchemy.engine.base.Engine ('zhou','[email protected]','456789',3)
2019-08-10 13:50:38,446 INFO sqlalchemy.engine.base.Engine COMMIT
複製程式碼

使用 filter_by 精確查詢: 查詢第一個和全部

>>> User.query.filter_by(name='wang').first()
2019-08-10 13:54:08,112 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.name AS users_name,users.email AS users_email,users.pswd AS users_pswd,users.role_id AS users_role_id 
FROM users 
WHERE users.name = %s 
 LIMIT %s
2019-08-10 13:54:08,113 INFO sqlalchemy.engine.base.Engine ('wang',1)
User:wang
>>> User.query.filter_by(name='wang').all()
2019-08-10 13:54:15,698 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.name = %s
2019-08-10 13:54:15,698 INFO sqlalchemy.engine.base.Engine ('wang',)
[User:wang]
複製程式碼

使用 filter 模糊查詢,返回結尾字元為 g 的所有資料:

>>> User.query.filter(User.name.endswith('g')).all()
2019-08-12 09:01:24,998 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE (users.name LIKE concat('%%',%s))
2019-08-12 09:01:24,999 INFO sqlalchemy.engine.base.Engine ('g',)
[User:wang,User:zhang]
複製程式碼

邏輯非:返回名字不等於 wang 的全部資料:

>>> User.query.filter(User.name!='wang').all()
2019-08-12 09:02:03,321 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.name != %s
2019-08-12 09:02:03,321 INFO sqlalchemy.engine.base.Engine ('wang',)
[User:zhang,User:chen,User:zhou]
複製程式碼

邏輯與,需要匯入 _and 返回and() 條件滿足的所有資料:

>>> User.query.filter(and_(User.name != 'wang',User.email.endswith('163.com'))).all()
2019-08-12 09:22:21,840 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.name != %s AND (users.email LIKE concat('%%',%s))
2019-08-12 09:22:21,841 INFO sqlalchemy.engine.base.Engine ('wang','163.com')
[User:zhou]
複製程式碼

邏輯或,需要匯入 or_

>>> from sqlalchemy import or_
>>> User.query.filter(or_(User.name != "wang",User.email.endswith('163.com'))).all()
2019-08-12 09:24:17,577 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.name != %s OR (users.email LIKE concat('%%',%s))
2019-08-12 09:24:17,577 INFO sqlalchemy.engine.base.Engine ('wang','163.com')
[User:wang,User:zhang,User:zhou]
複製程式碼

not_ 相當於取反

>>> from sqlalchemy import not_
>>> User.query.filter(not_(User.name == "chen")).all()
2019-08-12 09:25:49,716 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.name != %s
2019-08-12 09:25:49,716 INFO sqlalchemy.engine.base.Engine ('chen',User:zhou]
複製程式碼

查詢資料後刪除

>>> user = User.query.first()
2019-08-12 09:26:58,334 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
 LIMIT %s
2019-08-12 09:26:58,334 INFO sqlalchemy.engine.base.Engine (1,)
>>> user
User:wang
>>> db.session.delete(user) 
>>> db.session.commit()
2019-08-12 09:27:27,209 INFO sqlalchemy.engine.base.Engine DELETE FROM users WHERE users.id = %s
2019-08-12 09:27:27,209 INFO sqlalchemy.engine.base.Engine (1,)
2019-08-12 09:27:27,225 INFO sqlalchemy.engine.base.Engine COMMIT
>>> User.query.all()
2019-08-12 09:27:36,097 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-12 09:27:36,098 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users
2019-08-12 09:27:36,098 INFO sqlalchemy.engine.base.Engine ()
[User:zhang,User:zhou]
複製程式碼

更新資料:

>>> user = User.query.first()
2019-08-12 09:28:09,206 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
 LIMIT %s
2019-08-12 09:28:09,206 INFO sqlalchemy.engine.base.Engine (1,)
>>> user 
User:zhang
>>> user.name
'zhang'
>>> user.name = "furuiyang"
>>> db.session.commit()
2019-08-12 09:28:34,955 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=%s WHERE users.id = %s
2019-08-12 09:28:34,955 INFO sqlalchemy.engine.base.Engine ('furuiyang',2)
2019-08-12 09:28:34,960 INFO sqlalchemy.engine.base.Engine COMMIT
>>> User.query.first()
2019-08-12 09:28:46,551 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-08-12 09:28:46,552 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
 LIMIT %s
複製程式碼

2019-08-12 09:28:46,552 INFO sqlalchemy.engine.base.Engine (1,) User:furuiyang

使用 update 更新資料:

>>> User.query.filter_by(name='furuiyang').update({"name": "Katrina"})
2019-08-12 09:30:38,053 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE users.id = %s
2019-08-12 09:30:38,054 INFO sqlalchemy.engine.base.Engine (3,)
2019-08-12 09:30:38,058 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,059 INFO sqlalchemy.engine.base.Engine (4,060 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=%s WHERE users.name = %s
2019-08-12 09:30:38,060 INFO sqlalchemy.engine.base.Engine ('Katrina','furuiyang')
1
>>> User.query.all()
2019-08-12 09:31:00,951 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users
2019-08-12 09:31:00,951 INFO sqlalchemy.engine.base.Engine ()
[User:Katrina,User:zhou]
複製程式碼

關聯查詢示例: 角色和使用者是一對多的關係。一個角色可以有多個使用者,但是一個使用者只能屬於一個角色:

查詢某個角色組(ruiyang) 下的全部使用者:

>>> role_ruiyang = Role.query.filter_by(name='ruiyang').first() 
2019-08-12 09:35:24,302 INFO sqlalchemy.engine.base.Engine SELECT roles.id AS roles_id,roles.name AS roles_name 
FROM roles 
WHERE roles.name = %s 
 LIMIT %s
2019-08-12 09:35:24,302 INFO sqlalchemy.engine.base.Engine ('ruiyang',1)
>>> role_ruiyang 
Role:ruiyang
>>> role_ruiyang.us
2019-08-12 09:35:41,776 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id,users.role_id AS users_role_id 
FROM users 
WHERE %s = users.role_id
2019-08-12 09:35:41,776 INFO sqlalchemy.engine.base.Engine (3,)
[User:zhou]
複製程式碼

查詢某個使用者所屬的角色:

>>> user = User.query.get(3) 
>>> user
User:chen
>>> user.role
Role:user1
複製程式碼

資料庫遷移之 Flask-Migrate

安裝

pip install flask-migrate
複製程式碼

建立一個測試 app

如下:定義了兩個模型類,作者和書名:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)


class Author(db.Model):
    """
    定義模型類-作者
    """
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32),unique=True)
    email = db.Column(db.String(64))
    au_book = db.relationship('Book',backref='author')

    def __str__(self):
        return f'Author:{self.name}'


class Book(db.Model):
    """
    定義模型類-書名
    """
    __tablename__ = 'books'
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    leader = db.Column(db.String(32))
    au_book = db.Column(db.Integer,db.ForeignKey('author.id'))

    def __str__(self):
        return f'Book:{self.info},{self.lead}'


if __name__ == "__main__":
    app.run()
複製程式碼

開啟 flask shell 建立表:

(ihome)  furuiyang@furuiyangdeMacBook-Pro  ~/codes/iHomeDemo   master  flask shell 
Python 3.7.3 (default,Jun 19 2019,07:38:49) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
App: app [production]
Instance: /Users/furuiyang/codes/iHomeDemo/instance
>>> from app import db 
>>> db.create_all()
複製程式碼

在資料庫中檢視創建出的表結構:

mysql> desc author;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | YES  | UNI | NULL    |                |
| email | varchar(64) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> desc books;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| info    | varchar(32) | YES  | UNI | NULL    |                |
| leader  | varchar(32) | YES  |     | NULL    |                |
| au_book | int(11)     | YES  | MUL | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
複製程式碼

生成一些測試資料:

>>> au1 = Author(name='八月長安',email='[email protected]')
>>> au2 = Author(name='餘秋雨',email='[email protected]')
>>> au3 = Author(name='馮唐',email='[email protected]')

>>> bk1 = Book(info='最好的我們',leader='耿耿&餘淮')
>>> bk2 = Book(info='文化苦旅',leader='風景抒情')
>>> bk3 = Book(info='萬物生長',leader='秋水')
>>> db.session.add_all([au1,au2,au3,bk1,bk2,bk3])
>>> db.session.commit()
複製程式碼

檢視資料庫:

mysql> select * from author;
+----+--------------+-----------------+
| id | name         | email           |
+----+--------------+-----------------+
|  1 | 八月長安     | [email protected] |
|  2 | 餘秋雨       | [email protected]   |
|  3 | 馮唐         | [email protected]    |
+----+--------------+-----------------+
3 rows in set (0.00 sec)

mysql> select * from books;
+----+-----------------+---------------+---------+
| id | info            | leader        | au_book |
+----+-----------------+---------------+---------+
|  1 | 最好的我們      | 耿耿&餘淮     |    NULL |
|  2 | 文化苦旅        | 風景抒情      |    NULL |
|  3 | 萬物生長        | 秋水          |    NULL |
+----+-----------------+---------------+---------+
3 rows in set (0.00 sec)
複製程式碼

新增一個模板展示頁面:

<h1>書籍展示</h1>
    <form method="post">
        {{ form.csrf_token }}
        <p>作者:{{ form.au_info }}</p>
        <p>書名:{{ form.bk_info }}</p>
        <p>{{ form.submit }}</p>
    </form>
    <ul>
        <li>{% for x in author %}</li>
        <li>{{ x }}</li><a href='/delete_author{{ x.id }}'>刪除</a>
        <li>{% endfor %}</li>
    </ul>
    <hr>
    <ul>
        <li>{% for x in book %}</li>
        <li>{{ x }}</li><a href='/delete_book{{ x.id }}'>刪除</a>
        <li>{% endfor %}</li>
    </ul>
複製程式碼

新增檢視路由:

from flask import Flask,url_for
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

app.config['SECRET_KEY'] = 'ruiyang'

db = SQLAlchemy(app)


class Author(db.Model):
    """
    定義模型類-作者
    """
    __tablename__ = 'author'
    id = db.Column(db.Integer,{self.leader}'


class Append(Form):
    """建立表單類,用來新增資訊"""
    au_info = StringField(validators=[DataRequired()])
    bk_info = StringField(validators=[DataRequired()])
    submit = SubmitField(u'新增')


@app.route('/','POST'])
def index():
    # 查詢所有作者和書名資訊
    author = Author.query.all()
    book = Book.query.all()
    # 建立表單物件
    form = Append()
    if form.validate_on_submit():
        # 獲取表單輸入資料
        wtf_au = form.au_info.data
        wtf_bk = form.bk_info.data
        # 把表單資料存入模型類
        db_au = Author(name=wtf_au)
        db_bk = Book(info=wtf_bk)
        # 提交會話
        db.session.add_all([db_au,db_bk])
        db.session.commit()
        # 新增資料後,再次查詢所有作者和書名資訊
        author = Author.query.all()
        book = Book.query.all()
        return render_template('index.html',author=author,book=book,form=form)
    else:
        if request.method == 'GET':
            render_template('index.html',form=form)
    return render_template('index.html',form=form)


@app.route('/delete_author<id>')
def delete_author(id):
    """刪除作者"""
    # 精確查詢需要刪除的作者id
    au = Author.query.filter_by(id=id).first()
    db.session.delete(au)
    # 直接重定向到index檢視函式
    return redirect(url_for('index'))


@app.route('/delete_book<id>')
def delete_book(id):
    """刪除書名"""
    # 精確查詢需要刪除的書名id
    bk = Book.query.filter_by(id=id).first()
    db.session.delete(bk)
    # 直接重定向到index檢視函式
    return redirect(url_for('index'))


if __name__ == "__main__":
    app.run(debug=True)
複製程式碼

在 app 中加入擴充套件

建立遷移資料庫

(ihome)  ✘ furuiyang@furuiyangdeMacBook-Pro  ~/codes/iHomeDemo   master ●✚  flask db init 
  Creating directory /Users/furuiyang/codes/iHomeDemo/migrations ... done
  Creating directory /Users/furuiyang/codes/iHomeDemo/migrations/versions ... done
  Generating /Users/furuiyang/codes/iHomeDemo/migrations/script.py.mako ... done
  Generating /Users/furuiyang/codes/iHomeDemo/migrations/env.py ... done
  Generating /Users/furuiyang/codes/iHomeDemo/migrations/README ... done
  Generating /Users/furuiyang/codes/iHomeDemo/migrations/alembic.ini ... done
複製程式碼

建立遷移資料指令碼

(ihome)  furuiyang@furuiyangdeMacBook-Pro  ~/codes/iHomeDemo   master ●✚  flask db migrate -m 'first' 
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'author'
INFO  [alembic.autogenerate.compare] Detected added table 'books'
  Generating /Users/furuiyang/codes/iHomeDemo/migrations/versions/947c0bffbb1b_first.py ... done
複製程式碼

使用遷移指令碼更新資料庫

(ihome)  furuiyang@furuiyangdeMacBook-Pro  ~/codes/iHomeDemo   master ●✚  flask db upgrade 
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 947c0bffbb1b,first
複製程式碼

資料庫變動

檢視歷史版本

flask db history 
複製程式碼

版本回退

flask db downgrade 版本號
複製程式碼

註冊shell上下文

在我們啟動 flask shell的時候,我們就實現了在上下文中啟動了一個python 直譯器。這意味著我們可以有了當前的應用例項:

使用常規的直譯器會話時,除非明確地被匯入,否則app物件是未知的,但是當使用flask shell時,該命令預先匯入應用例項。 flask shell的絕妙之處不在於它預先匯入了app,而是你可以配置一個“shell上下文”,也就是可以預先匯入一份物件列表。

在入口指令碼中實現一個函式,通過新增資料庫例項和模型來建立了一個shell上下文環境:

from app import app,db
from app.models import User,Post

@app.shell_context_processor
def make_shell_context():
    return {'db': db,'User': User,'Post': Post}
複製程式碼

app.shell_context_processor裝飾器將該函式註冊為一個shell上下文函式。 當flask shell命令執行時,它會呼叫這個函式並在shell會話中註冊它返回的專案。 函式返回一個字典而不是一個列表,原因是對於每個專案,你必須通過字典的鍵提供一個名稱以便在shell中被呼叫。