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()方法中傳參,html

好比咱們能夠經過python hello.py runserver --host ip地址,告訴服務器在哪一個網絡接口監聽來自客戶端的鏈接。默認狀況下,服務器只監聽來自服務器所在計算機發起的鏈接,即localhost鏈接。python

咱們能夠經過 python hello.py runserver --help 來查看參數:mysql

Flask-WTF

相關參考連接

github.com/luhuisicnu/…git

關於 web 表單

web表單是web應用程序的基本功能。 它是HTML頁面中負責數據採集的部件。表單有三個部分組成:表單標籤、表單域、表單按鈕。表單容許用戶輸入數據,負責HTML頁面數據採集,經過表單將用戶輸入的數據提交給服務器。github

在Flask中,爲了處理web表單,咱們通常使用Flask-WTF擴展,它封裝了WTForms,而且它有驗證表單數據的功能。web

WTForms支持的HTML標準字段

WTForms經常使用驗證函數

表單中的 CSRF

使用Flask-WTF須要配置參數SECRET_KEY。 CSRF_ENABLED是爲了CSRF(跨站請求僞造)保護。 SECRET_KEY用來生成加密令牌,當CSRF激活的時候,該設置會根據設置的密匙生成加密令牌。sql

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

文件結構:shell

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.pyflask

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, request, 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('/', methods=['GET', '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:ruiyang@127.0.0.1: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:ruiyang@127.0.0.1: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, primary_key=True)
    name = db.Column(db.String(64), 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='wang@163.com', pswd='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='zhang@189.com', pswd='201512', role_id=ro2.id)
    us3 = User(name='chen', email='chen@126.com', pswd='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='zhou@163.com', 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',email='wang@163.com',pswd='123456',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',email='zhang@189.com',pswd='201512',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',email='chen@126.com',pswd='987654',role_id=role1.id)
>>> us4 = User(name='zhou',email='zhou@163.com',pswd='456789',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,us2,us3,us4])
>>> db.session.commit()
2019-08-10 13:50:38,442 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, email, pswd, role_id) VALUES (%s, %s, %s, %s)
2019-08-10 13:50:38,442 INFO sqlalchemy.engine.base.Engine ('wang', 'wang@163.com', '123456', 1)
2019-08-10 13:50:38,444 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, email, pswd, role_id) VALUES (%s, %s, %s, %s)
2019-08-10 13:50:38,444 INFO sqlalchemy.engine.base.Engine ('zhang', 'zhang@189.com', '201512', 2)
2019-08-10 13:50:38,445 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, email, pswd, role_id) VALUES (%s, %s, %s, %s)
2019-08-10 13:50:38,445 INFO sqlalchemy.engine.base.Engine ('chen', 'chen@126.com', '987654', 2)
2019-08-10 13:50:38,446 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, email, pswd, role_id) VALUES (%s, %s, %s, %s)
2019-08-10 13:50:38,446 INFO sqlalchemy.engine.base.Engine ('zhou', 'zhou@163.com', '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.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
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.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 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.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
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.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 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.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 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:chen, 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.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
2019-08-12 09:25:49,716 INFO sqlalchemy.engine.base.Engine ('chen',)
[User:wang, User:zhang, 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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, 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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, users.role_id AS users_role_id 
FROM users
2019-08-12 09:27:36,098 INFO sqlalchemy.engine.base.Engine ()
[User:zhang, User:chen, 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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, 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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, 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.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.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, 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.id = %s
2019-08-12 09:30:38,059 INFO sqlalchemy.engine.base.Engine (4,)
2019-08-12 09:30:38,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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, users.role_id AS users_role_id 
FROM users
2019-08-12 09:31:00,951 INFO sqlalchemy.engine.base.Engine ()
[User:Katrina, User:chen, 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.name AS users_name, users.email AS users_email, users.pswd AS users_pswd, 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:ruiyang@127.0.0.1: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='changan@163.com')
>>> au2 = Author(name='餘秋雨',email='qiuyu@126.com')
>>> au3 = Author(name='馮唐',email='tang@163.com')

>>> 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 | 八月長安     | changan@163.com |
|  2 | 餘秋雨       | qiuyu@126.com   |
|  3 | 馮唐         | tang@163.com    |
+----+--------------+-----------------+
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, render_template, request, redirect, 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:ruiyang@127.0.0.1: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, 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.leader}'


class Append(Form):
    """建立表單類,用來添加信息"""
    au_info = StringField(validators=[DataRequired()])
    bk_info = StringField(validators=[DataRequired()])
    submit = SubmitField(u'添加')


@app.route('/', methods=['GET', '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', author=author, book=book, form=form)
    return render_template('index.html', author=author, book=book, 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中被調用。

相關文章
相關標籤/搜索