<后端>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>
现象