<后端>Flask框架

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>

  

现象

原文地址:https://www.cnblogs.com/shuimohei/p/11456143.html