Flask小案例

前言

Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。

Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。

其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。

本文将利用flask结合mysql数据库写一个前后端交互的简单的书籍管理系统的小案例

书籍管理系统需求介绍

library_page.png

界面分为两部分,上半部分可以根据用户输入的作者名称,书籍名称,添加信息。下半部分用来展示所有的作者及对应的书籍信息,并且可以做删除处理。数据存储在本地的mysql数据库中。

用到的模块有:Flask-SQLalchemy,Flask-WTF

1.创建模型类

分析:需要创建两个数据库表,Author表,Book表,对应关系为一对多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# 实例化flask对象
app = Flask(__name__)

"""
1. 如果安装的数据库驱动是flask_mysqldb 格式:
mysql://<用户名>:<密码>@<IP地址>:<端口>/<数据库名>
2. 如果安装的数据库驱动是pymysql 格式
mysql+pymysql://<用户名>:<密码>@<IP地址>:<端口>/<数据库名>
"""
# 我装的是flask_mysqldb,所以用第一种格式来配置数据库的连接
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:mysql@127.0.0.1:3306/library"

# 跟踪数据库变化,设置为False,可以减少性能损耗
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 设置密钥,等号右边的值可以随便设置
app.config['SECRET_KEY'] = 'ASDNAKNK'

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


# 编写模型类,继承db.Model
class Author(db.Model):
__tablename__ = "authors"
# 创建author表字段
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)

# 关系属性和反向引用
books = db.relationship("Book", backref='author')

# 为了方便的看到对象输出的内容__repr__, 如果是普通类用__str__
def __repr__(self):
return "Author:%s,%s" % (self.id, self.name)

class Book(db.Model):
__tablename__ = "books"
# 创建book表字段
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
# 设置外键,关联authors表
author_id = db.Column(db.Integer, db.ForeignKey(Author.id))

def __repr__(self):
return "Book:%s,%s" % (self.id, self.name)

if __name__ == '__main__':
db.drop_all()
db.create_all()
app.run(debug=True)

2.创建页面需要显示的表单

form.png

分析:页面包含作者及对应的输入框、书籍及对应的输入框、添加按钮

WTForms支持HTML标准字段,下面用的字段有StringField:文本字段,SubmitField:表单提交按钮 ;

用到的WTForms验证函数有DataRequired :用来确保字段中有值,即输入框有值

1
2
3
4
5
6
7
8
9
10
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

# 创建页面显示的表单
class BookForm(FlaskForm):
# 创建作者及对应的输入框,validators为验证器
author = StringField(label='作者:', validators=[DataRequired('作者不能为空')])
book = StringField(label='书籍:', validators=[DataRequired('书籍不能为空')])
submit = SubmitField(label="添加")

3.渲染到页面

  • 定义路由函数,并将 Author 和 Book 的所有结果传到模板
1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask, render_template, redirect

# 展示界面
@app.route('/')
def show_page():
# 创建表单
bookform = BookForm()
# 查询数据库
authors = Author.query.all()
books = Book.query.all()

# 渲染到页面
return render_template("demo03_library.html", form=bookform, authors=authors, books=books)
  • 模版代码的代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>

    <form action="", method="post">
    {# 添加隐藏的csrf_token字段,防止csrf攻击 #}
    {{ bookForm.csrf_token }}

    {# 作者及输入框 #}
    {{ bookForm.authorName.label }}
    {{ bookForm.authorName }}<br>

    {# 书籍及输入框 #}
    {{ bookForm.bookName.label }}
    {{ bookForm.bookName }}<br>

    {# 添加按钮 #}
    {{ bookForm.submit }}<br>
    </form>
    <hr>
    <ul>
    {# 在页面下半部分展示作者及书籍信息 #}
    {% for author in authors %}
    <li>作者: {{ author.name }}</li>
    <ul>
    {# 编写模型类时在Author类设置了关系属性relationship,所以这里可以用author的books属性直接查询到某个作者对应的所有书籍 #}
    {% for book in author.books %}
    <li>书籍: {{ book.name }}</li>
    {% endfor %}
    </ul>
    {% endfor %}
    </ul>
    </body>
    </html>

4.制作添加的功能

功能:用户在页面输入作者及书籍信息后,点击添加按钮,可以将数据添加到数据库中

代码逻辑分析:1.如果作者存在,书籍存在,不能添加
2.如果作者存在,书籍不存在,可以添加
3.如果作者不存在, 可以添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from flask import render_template, redirect, flash, url_for

# 添加书籍的路由函数
@app.route('/add_book', methods=['POST'])
def add_book():
# 1.创建表单,验证提交的数据
bookform = BookForm()

# 2.验证--validate_on_submit()
if bookform.validate_on_submit():
# 走到这,说明通过验证,所以获取用户输入的参数
author_name = bookform.author.data
book_name = bookform.book.data

# 通过输入的作者名称,查询数据库中的作者
author = Author.query.filter(Author.name == author_name).first()

# 判断作者是否存在
if author:
# 作者存在,判断书籍是否存在
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()

# 添加完成,重定向到展示页面(刷新)
return redirect(url_for('show_page'))

用户在点击提交按钮后,需要跳转到添加书籍的路由函数,所以在模板中设置form的action属性为 ‘/add_book’,并将flash信息打印出来,HTML的代码修改如下:

1
2
3
4
5
6
<form action="/add_book", method="post">
.....
{% for message in get_flashed_messages() %}
<p style="color: red">{{ message }}</p>
{% endfor %}
</form>

5.制作删除的功能

功能:用户点击删除作者 或者 删除书籍 可以将对应得数据从数据库中删除

代码逻辑分析:

1.点击删除书籍:通过获取对于的书籍在数据库表中的id删除对应的书籍

2.点击删除作者按钮:先删除作者对应的书籍,再删除作者

编写删除的路由函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 删除书籍
@app.route('/delete_book/<int:book_id>')
def delete_book(book_id):
# 1.根据编号获取书籍对象
book = Book.query.get(book_id)

# 2.删除书籍
db.session.delete(book)
db.session.commit()

# 3. 重定向展示界面
return redirect(url_for('show_page'))


# 删除作者
@app.route('/delete_author/<int:author_id>')
def delete_author(author_id):
# 1.根据编号获取书籍对象
author = Author.query.get(author_id)

# 2.删除该作者书籍
for book in author.books:
db.session.delete(book)

# 3.删除作者对象
db.session.delete(author)
db.session.commit()

# 4. 重定向展示界面
return redirect(url_for('show_page'))

在模板中添加删除的标签,使用url_for(),可以通过路由函数拿到对应的url,并将对于的author_id和book_id添加到路由中,修改的html代码如下:

1
2
3
4
5
6
7
8
9
10
<ul>
{% for author in authors %}
<li>作者:{{ author.name }}</li><a href="{{ url_for('delete_author',author_id=author.id) }}">删除作者</a>
<ul>
{% for book in author.books %}
<li id="b">书籍:{{ book.name }}</li><a href="{{ url_for('delete_book',book_id=book.id) }}">删除书籍</a>
{% endfor %}
</ul>
{% endfor %}
</ul>

总结

至此就完成了一个简单的flask的小案例,整体步骤:配置mysql的连接-->创建要用到的模型类-->创建wtf表单并渲染到页面-->编写业务功能

Flask常用扩展包:

  • Flask-SQLalchemy:操作数据库;
  • Flask-script:插入脚本;
  • Flask-migrate:管理迁移数据库;
  • Flask-Session:Session存储方式指定;
  • Flask-WTF:表单;
  • Flask-Mail:邮件;
  • Flask-Bable:提供国际化和本地化支持,翻译;
  • Flask-Login:认证用户状态;
  • Flask-OpenID:认证;
  • Flask-RESTful:开发REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和时间;
  • Flask-Admin:简单而可扩展的管理接口的框架
------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!
0%