• <后端>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>
    

      

    现象

  • 相关阅读:
    Intellij IDEA + Jrebel
    WebConfig配置详解大全
    .Net 获取前端传递的数据
    js 格式验证大全
    EasyUI DataGrid 时间格式化、字符串长度截取
    SQL取某个字符串最后一次出现的位置后面的字符串方法
    公民身份号码校验码算法(C#版)
    组织机构代码校验码生成算法(C#版)
    MySQL实现根据当前ID读取上一条和下一条记录
    js jquery.pagination.js分页
  • 原文地址:https://www.cnblogs.com/shuimohei/p/11456143.html
Copyright © 2020-2023  润新知