1.Flask框架安装
简介:轻量级WEB框架,类似于简单版本的Django
pip install flask
-
环境文件生成
pip freeze > requirement.txt
-
环境文件安装
pip install -r requirement.txt
2. 简单入门
# 1.导入FlasK扩展
from flask import Flask, render_template
# 2.创建Flask应用实例,需要传入__name__,确定资源路径
app = Flask(__name__)
# 3.定义路由及视图函数,装饰器实现路由
# 请求方式,利用methods自行指定
@app.route('/', methods=['GET', 'POST'])
def hello_world():
# 传值
url_str = 'www.baidu.com'
my_list = [1, 2, 3, 4, 5, 6]
my_dist = {
'name':'123',
'age' : '13',
}
# 可以返回,字符串和模板
return render_template('index.html', url_str=url_str, my_list=my_list, my_dist=my_dist)
# 6.路由参数获取和限定,int:限定,强制转换,成功既可以访问,float:同理
@app.route('/orders/<int:order_id>')
def get_order_id(order_id):
# 路由的访问优化
return 'order_id %s' % order_id
# return 'Hello World!'
# 4.启动程序
if __name__ == '__main__':
# 执行后,Flask运行在简易服务器,用于测试
app.run()
3.模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>index</title>
</head>
<body>
<h1>变量代码块</h1>
{# 注释在这里 #}
<a href="{{ url_str}}">百度</a> <br>
{{ my_list }} <br>
{{ my_list.1 }} <br>
{{ my_list[2] }} <br>
{{ my_dist }} <br>
{{ my_dist['name'] }} <br>
<hr>
<h1>控制代码块</h1>
{#for 循环的使用#}
{% for num in my_list %}
{# if判断的使用#}
{% if num > 3 %}
{{ num }} <br>
{% endif %}
{% endfor %}
<h1>过滤器</h1>
{#转大写#}
{{ url_str | upper }} <br>
{#字符串反转#}
{{ url_str | reverse }} <br>
{# 链式调用 #}
{{ url_str | upper | reverse | lower | reverse}} <br>
</body>
</html>
4.表单
table_index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>table</title>
</head>
<body>
<form method="post">
<lable>用户名:</lable><input type="text" name="username"><br>
<lable>密码:</lable><input type="password" name="password"><br>
<lable>确认密码:</lable><input type="password" name="password2"><br>
<input type="submit" value="提交"><br>
{#获取app中flash输出的内容#}
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
</form>
</body>
</html>
app.py
# 1.导入FlasK扩展
from flask import Flask, render_template,request,flash
# 2.创建Flask应用实例,需要传入__name__,确定资源路径
app = Flask(__name__)
# 加密
app.secret_key = 'jiami'
# 3.定义路由及视图函数,装饰器实现路由
# 请求方式,利用methods自行指定
@app.route('/', methods=['GET', 'POST'])
def hello_world():
# 传值
url_str = 'www.baidu.com'
my_list = [1, 2, 3, 4, 5, 6]
my_dist = {
'name': '123',
'age': '13',
}
# 可以返回,字符串和模板
return render_template('index.html', url_str=url_str, my_list=my_list, my_dist=my_dist)
@app.route('/table', methods=['GET', 'POST'])
def table_index():
# request: 请求对象
if request.method == 'POST':
# 获取请求参数
username = request.form.get("username")
password = request.form.get("password")
password2 = request.form.get("password2")
print(username,password,password2)
if not all([username,password,password2]):
# flash发消息,发送给模板,消息需要加密secret_key
flash(u"参数不完整")
elif password != password2:
flash(u"密码不一致")
else:
return "登录成功"
# return request.method
return render_template('table_index.html')
# 6.路由参数获取和限定,int:限定,强制转换,成功既可以访问,float:同理
@app.route('/orders/<int:order_id>')
def get_order_id(order_id):
# 路由的访问优化
return 'order_id %s' % order_id
# return 'Hello World!'
# 4.启动程序
if __name__ == '__main__':
# 执行后,Flask运行在简易服务器,用于测试
app.run()
5.flask-WTF(类似Django)
安装
pip install flask-wtf
app.py
# 导入FlasK扩展
from flask import Flask, render_template, request
from flask import flash
# 导入WTF扩展表单类
from flask_wtf import FlaskForm
# 导入自定义表单需要的字段
from wtforms import StringField, PasswordField, SubmitField
# 导入WTF扩展提供的表单验证器,有数据,比较相等,验证长度,验证数字范围,url
from wtforms.validators import DataRequired, EqualTo, length, NumberRange
# 创建Flask应用实例,需要传入__name__,确定资源路径
app = Flask(__name__)
# 加密
app.secret_key = '123456'
# 自定义表单类
class LoginForm(FlaskForm):
uesrname = StringField('用户名', validators=[DataRequired()])
password = PasswordField('密码', validators=[DataRequired()])
password2 = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password', '密码不一致')])
submit = SubmitField('提交')
@app.route('/', methods=['GET', 'POST'])
def login():
login_form = LoginForm()
# 验证逻辑
if request.method == 'POST':
username = request.form.get("username")
password = request.form.get("password")
password2 = request.form.get("password2")
# 验证参数,提交即验证
# 没有CSRF_token验证
if login_form.validate_on_submit():
return '验证成功'
else:
print(password,password2)
# 需要在模板中先进行渲染
flash(u'消息有误')
return render_template('table_WTF.html', form=login_form)
# 启动程序
if __name__ == '__main__':
# 执行后,Flask运行在简易服务器,用于测试
app.run()
table_WTF.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>table_WTF</title>
</head>
<body>
<form method="post">
<lable>用户名:</lable><input type="text" name="username"><br>
<lable>密码:</lable><input type="password" name="password"><br>
<lable>确认密码:</lable><input type="password" name="password2"><br>
<input type="submit" value="提交"><br>
</form>
<hr>
<form method="post">
{{ form.csrf_token() }}
{{ form.uesrname.label }} {{ form.uesrname }} <br>
{{ form.password.label }} {{ form.password }} <br>
{{ form.password2.label }} {{ form.password2 }} <br>
{{ form.submit }} <br>
{#获取app中flash输出的内容#}
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
</form>
</body>
</html>
6.flask使用数据库
安装
pip install flask-sqlalchemy
连接mysql还需要安装
pip install flask-mysqldb
# 导入FlasK扩展
from flask import Flask
# 引入数据库扩展
from flask_sqlalchemy import SQLAlchemy
# 创建Flask应用实例,需要传入__name__,确定资源路径
app = Flask(__name__)
# 配置数据库地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1/flask_sql'
# 跟踪数据库更改--不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
"""表模型创建"""
db = SQLAlchemy(app)
# 继承db.Model,代表数据库模型
class Role(db.Model):
# 表名
__tablename__ = 'roles'
# 字段名
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16), unique=True)
class User(db.Model):
# 表名
__tablename__ = 'users'
# 字段名
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16), unique=True)
# 表名.id实现外键
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
# 创建表的位置必须放在模型下方
# 删除表
db.drop_all()
# 创建表
db.create_all()
@app.route('/', methods=['GET', 'POST'])
def login():
return 'hello'
# 启动程序
if __name__ == '__main__':
# 执行后,Flask运行在简易服务器,用于测试
app.run(debug=True)
增删改操作
'''
In [1]: from app import *
# 增加,增加多个add_all([uesr1,user2])
In [2]: role = Role(name='admin')
In [3]: db.session.add(role)
In [4]: db.session.commit()
In [5]: user = User(name='xiaohei',role_id=role.id)
In [6]: db.session.add(user)
In [7]: db.session.commit()
修改
In [8]: user.name = 'xiaobai'
In [9]: db.session.commit()
删除
In [15]: db.session.delete(user)
In [16]: db.session.commit()
'''
7.综合案例
app.py
# 0.导入FlasK扩展
# 7.重定向redirect, url_for
from flask import Flask, render_template, request, flash, redirect, url_for
# 1.引入数据库扩展
from flask_sqlalchemy import SQLAlchemy
# 5.继承FlaskForm
from flask_wtf import FlaskForm
# 5. 导入模型
from wtforms import StringField, SubmitField
# 5. 表单验证
from wtforms.validators import DataRequired
'''
1.配置数据库:引入扩展,配置数据库,创建数据库对象,使用终端创建数据库
2.添加模型:添加书和作者的模型
3.添加数据: 直接添加
4.使用模板显示数据库查询数据:查询所有作者信息,作者获取数据用的是关系引用
5.WTF表单显示:自定义表单类,模板中显示,secret_key/编码/csrf_token
6.实现相关增加逻辑
7.实现相关删除逻辑:穿ID,路由接收参数
'''
# 创建Flask应用实例,需要传入__name__,确定资源路径
app = Flask(__name__)
# 1.配置数据库
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1/flask_books'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 5.secret_key
app.secret_key = '123456'
# 1.创建数据库对象
db = SQLAlchemy(app)
# 1.在终端创建flask_books数据库:create database flask_books charset=utf8
# 2.定义书模型
# 继承db.Model,代表数据库模型
class Book(db.Model):
# 表名
__tablename__ = 'books'
# 字段名:ID,书名,外键author_id---author引用
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16), unique=True)
# 外键
author_id = db.Column(db.Integer, db.ForeignKey('authors.id'))
# repr()显示一个可读字符串
def __repr__(self):
return '<Book:%s %s>' % (self.name, self.author_id)
# 2.定义作者模型
class Author(db.Model):
# 表名
__tablename__ = 'authors'
# 字段名:ID,名字,---books引用
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16), unique=True)
# 关系引用books是Author模型用,author是Book模型用的
books = db.relationship('Book', backref='author')
# 方便查看
def __repr__(self):
return '<author:%s %s>' % (self.name, self.id)
# TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given
# 原因:DataRequired没有加括号
# 5.自定义表单类
class AuthorForm(FlaskForm):
author = StringField('作者', validators=[DataRequired()])
book = StringField('书籍', validators=[DataRequired()])
submit = SubmitField('提交')
# 3.添加数据
# 删除表
db.drop_all()
# 创建表
db.create_all()
au1 = Author(name='张三')
au2 = Author(name='李四')
au3 = Author(name='王五')
au4 = Author(name='赵六')
# 数据给会话,提交会话
db.session.add_all([au1, au2, au3, au4])
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)
bk6 = Book(name='赵六的一生', author_id=au4.id)
# 数据给会话,提交会话
db.session.add_all([bk1, bk2, bk3, bk4, bk5, bk6])
db.session.commit()
# 7.删除数据的路由
@app.route('/delete_book/<book_id>')
def delete_book(book_id):
# 查询数据库,是否有该ID的书,有就删除,没有报错
# 删除书
book =Book.query.get(book_id)
if book:
try:
db.session.delete(book)
db.session.commit()
except Exception as e:
print(e)
flash('删除书籍出错')
db.session.rollback()
else:
flash('书籍找不到')
# 如何返回当前网址,重定向
# redirect需要传入网址/路由地址
# url_for()需要传入视图函数名,返回该视图函数对应的路由地址
print(url_for('login'))
return redirect(url_for('login'))
# 8.删除作者
@app.route('/delete_author/<author_id>')
def delete_author(author_id):
# 查询作者,先删书,在删作者
author = Author.query.get(author_id)
if author:
try:
# 查询后直接删除
Book.query.filter_by(author_id=author_id).delete()
# 删除作者
db.session.delete(author)
db.session.commit()
except Exception as e:
print(e)
flash('删除作者出错')
db.session.rollback()
else:
flash("作者找不到")
return redirect(url_for('login'))
# 4:将数据信息,传给模板
@app.route('/', methods=['GET', 'POST'])
def login():
# 4.查询作者信息,传给模板
authors = Author.query.all()
# 5.创建自定义表单类
author_form = AuthorForm()
# 6.调用WTF验证函数实现验证
if author_form.validate_on_submit():
# 6.验证通过获取数据
author_name = author_form.author.data
book_name = author_form.book.data
# 6.查询数据,判断是否存在,是否存在重复,增加相应数据
author = Author.query.filter_by(name=author_name).first()
if author:
# 作者存在,查询数据
book = Book.query.filter_by(name=book_name).first()
if book:
flash('已存在重复书籍')
else:
try:
new_book = Book(name=book_name, author_id=author.id)
db.session.add(new_book)
db.session.commit()
except Exception as e:
print(e)
flash("添加书籍失败")
# 回滚
db.session.rollback()
else:
# 作者不存在
try:
new_author = Author(name=author_name)
db.session.add(new_author)
db.session.commit()
new_book = Book(name=book_name, author_id=new_author.id)
db.session.add(new_book)
db.session.commit()
except Exception as e:
print(e)
flash("添加作者和书籍失败")
# 回滚
db.session.rollback()
else:
if request.method == 'post':
# 6.验证出错,提示错误
flash('参数错误')
return render_template('books.html', authors=authors, form=author_form)
# 启动程序
if __name__ == '__main__':
# 执行后,Flask运行在简易服务器,用于测试
app.run(debug=True)
books.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>books</title>
</head>
<body>
{#5.表单显示#}
<form method="post">
{{ form.csrf_token() }}
{{ form.author.label }}{{ form.author }} <br>
{{ form.book.label }}{{ form.book }} <br>
{{ form.submit }} <br>
{#获取app中flash输出的内容#}
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
</form>
<hr>
{#4.先遍历作者,然后作者下方遍历书籍#}
<ul>
{# 遍历传入的作者信息 #}
{% for author in authors %}
<li>{{ author.name }}<a href="{{ url_for("delete_author", author_id=author.id) }}">删除</a></li>
<ul>
{# 根据作者找到书籍,遍历数据的名称#}
{% for book in author.books %}
<li>{{ book.name }}<a href="{{ url_for("delete_book", book_id=book.id) }}">删除</a></li>
{% else %}
<li>无</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
</body>
</html>
现象