初识flash板书设计(初识Flask)
初识Flask
Flask简介
Flask是一个基于Python的web框架 ,由奥地利开发商Armin Ronacher于2010年4月1日发布 。它以灵活 、“微 ”框架著称 ,其本身并不具备太多的功能 ,但通过丰富的第三方插件 ,使其在保持重量轻和简单的同时仍然可以进行高度扩展 ,让开发者能轻松应对现实开发中复杂的需求 。
Flask vs Django
Django功能大而全 ,Flask只包含基本的配置; Flask 比 Django 扩展性更好 。安装Flask
打开cmd窗口 ,执行如下指令即可安装 。
pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple执行如下指令查看是否安装成功 。
pip list第一个Flask项目(使用Pycharm)
打开PyCharm ,选择New Project新建一个项目 ,之后点击左侧Flask ,再选择项目存放路径以及Python解释器路径 ,点击Create即可 。
创建成功后 ,项目结构如下 。
flask_01
│ app.py:项目入口文件 。
├─static:存放静态文件(js 、css 、image等)的文件夹,初始为空 。
└─templates:存Jinjia2模板的文件夹 ,初始为空 。app.py初始内容如下 。
from flask import Flask # 从flask包中导入Flask类 app = Flask(__name__) # 实例化Flask类 # __name__:代表当前app.py这个模块 ,其作用为 1.以后出现bug,可以帮助我们快速定位;2.对于寻找模板文件 ,有一个相对路径 @app.route(/) # 创建一个路由和视图函数的映射 ,/代表根路由 def hello_world(): # 当访问根路由时会执行此函数 return Hello World! if __name__ == __main__: app.run() # 运行项目项目配置
debug模式
开启debug模式后 ,只要修改代码后保存 ,项目就会重新加载 ,无需手动重启项目 ,且开发时如果遇到bug ,可以在浏览器上看到出错信息 。
设置方法 法一首先点击Edit Configurations。
勾选FLASK_DEBUG后 ,点击OK即可 。
法二在app.run() 中添加debug=True 。
app.run(debug=True) # 运行项目修改host
host即为监听的主机名 ,默认为127.0.0.1 ,修改host可以让其它电脑也能访问到本电脑的flask项目 ,修改步骤如下。
点击Edit Configurations 。
在Additional options处填写预设的host值 ,然后点击OK即可 。
修改port
port即为端口号,若要修改 ,同样在Additional options处修改即可 。
URL与视图
URL格式
协议://域名:端口号/path ,其中,path通过app.route()指定 。
URL与视图的关系
在URL中 ,http协议默认端口为80 ,https协议默认端口为443 ,在实际使用中默认端口号可以不填写 ,下方两个URL均能正确访问到百度地址 。
https://www.baidu.com
https://www.baidu.com:443
定义无参数的URL
敲写下方代码 ,程序运行后 ,可通过 127.0.0.1:8888/home 访问 。
@app.route(/home) def home(): return home定义有参数的URL
flask里通过<>来给path指定参数 。
参数类型
string:字符串类型 ,可以接受除/以外的字符 。
int:整型 ,可以接受能通过int()方法转换的字符 。
float:浮点型 ,可以接受能通过float()方法转换的字符 。
path:路径 ,类似string ,但是中间可以添加/ 。
uuid:UUID类型 ,UUID是一组32位数的16进制所构成 。
any:备选值中的任何一个(理解为枚举)。
类型一敲写下方代码,程序运行后 ,可通过 127.0.0.1:8888/home/任意数字 访问 。
@app.route(/home/<int:user_id>) # 类型的指定是可选的 def blog_detail(user_id): return 您是:%s % user_id 类型二敲写下方代码 ,程序运行后,可通过 127.0.0.1:8888/book/list?page=任意数字 访问 。
from flask import Flask, request # 从flask包中导入Flask类 # /book/list:返回第一页的数据 # /book/list?page=2:返回第二页的数据 @app.route(/book/list) def book_list(): # arguments: 参数 # request.args: 类字典类型 page = request.args.get("page", default=1, type=int) return f您获取的是第{page}页的图书列表Jinjia2模板
Jinjia2是一个Python模板语言 ,安装Flask时 ,Jinjia2会自动安装 ,Jinjia2模板语言是不分缩进的。
模板渲染
无参数渲染在templates创建文件index.html 。
index.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>这是首页 。</h1> </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) @app.route(/) def hello_world(): return render_template(index.html) if __name__ == __main__: app.run() # 运行项目 有参数渲染在templates创建文件user_detail.html 。
user_detail.html内容如下 ,Jinjia2通过{}来获取变量的值 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户详情</title> </head> <body> <h1>用户id是{{ user_id }}</h1> </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) @app.route(/home/<user_id>) def user_detail(user_id): return render_template(user_detail.html, user_id=user_id) if __name__ == __main__: app.run() # 运行项目模板访问对象属性
Jinjia2访问对象属性有两种方法 ,例如{{ user.user_name }}和{{ user[user_name] }} 。
index.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>{{ user.user_name }} + {{ user.user_email }}</h1> </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) class User: def __init__(self, user_name, user_email): self.user_name = user_name self.user_email = user_email @app.route(/) def hello_world(): user = User("lili", 123456@qq.com) return render_template(index.html, user=user) if __name__ == __main__: app.run()过滤器
在Python中 ,如果需要对某个变量进行处理 ,可以通过函数来实现;在模板中 ,则是通过过滤器来实现的 。过滤器本质上也是函数 ,在模板中使用管道符号(|)来调用 。例如有字符串类型变量name ,想要获取它的长度 ,可以通过{{name | length}}来获取 ,length是Jinjia2内置的过滤器,Jinjia2会把name当做第一个参数传给length过滤器底层对应的函数。
内置过滤器filter.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>filter_demo</title> </head> <body> 名字:{{ user.user_name }} 名字长度:{{ user.user_name|length }} </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) class User: def __init__(self, user_name, user_email): self.user_name = user_name self.user_email = user_email @app.route(/filter) def filte_page(): user = User(lili, 123@qq.com) return render_template(filter.html, user=user) if __name__ == __main__: app.run() 自定义过滤器过滤器本质上是Python的函数 ,它会把被过滤的值当做第一个参数传给这个函数 ,函数经过一些逻辑处理后,再返回新的值。在过滤器函数写好后 ,可以通过@app.template_filter装饰器或者app.add_template_filter函数来把函数注册成Jinjia2能用的过滤器 。
下方代码定义了一个date_format函数 ,第一个参数是需要被处理的值 ,第二个参数是时间的格式 ,并且指定了一个默认值 ,通过app.add_template_filter ,将date_format函数注册成了过滤器 ,并且过滤器的名字为d_format ,如果app.add_template_filter没有传第二个参数 ,那么默认将使用函数的名称来作为过滤器的名称 。
filter.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>filter_demo</title> </head> <body> 时间:{{ my_time|d_format }} </body> </html>app.py内容如下 。
from flask import Flask, render_template from datetime import datetime app = Flask(__name__) @app.route(/filter) def filte_page(): my_time = datetime.now() return render_template(filter.html, my_time=my_time) def date_format(value, format="%Y-%m-%d %H:%M"): return value.strftime(format) app.add_template_filter(date_format, d_format) if __name__ == __main__: app.run()控制语句
if语句filter.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>filter_demo</title> </head> <body> {% if age > 18 %} <div>您已满18岁</div> {% elif age == 18 %} <div>您刚满18岁</div> {% else %} <div>您未满18岁</div> {% endif %} </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) @app.route(/filter) def filte_page(): age = 17 return render_template(filter.html, age=age) if __name__ == __main__: app.run() for循环Jinjia2中的for循环没有break语句 。
filter.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>filter_demo</title> </head> <body> {% for student in students %} <div>学生姓名:{{ student.name }} ,学生年龄:{{ student.age }}</div> {% endfor %} </body> </html>app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) @app.route(/filter) def filte_page(): students = [ {name:lili, age:18}, {name:lucy, age:17}, {name:lfiv, age:19} ] return render_template(filter.html, students=students) if __name__ == __main__: app.run() # 运行项目模板继承
一个网站中 ,大部分网页的模块是重复的 ,比如顶部的导航栏 、底部的备案信息等,如果在每个页面中都重复地去写这些代码 ,会让项目变得臃肿 ,提高后期维护成本 。此时,可以通过模板继承 ,把一些重复性的代码写在父模板里 ,子模板继承父模板后 ,再分别实现自己的代码 。
父模板文件base.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> </head> <body> <ul> <li><a href="#">首页</a></li> <li><a href="#">新闻</a></li> </ul> {% block body %} {% endblock %} <footer>底部标签</footer> </body> </html>child1.html内容如下。
{% extends base.html %} {% block title %} 我是子模板 {% endblock %} {% block body %} 我是子模板的文字 {% endblock %}app.py内容如下 。
from flask import Flask, render_template app = Flask(__name__) @app.route(/child1) def child1(): return render_template(child1.html) if __name__ == __main__: app.run()加载静态文件
static.html内容如下 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>static_demo</title> <link rel="stylesheet" href="https://www.cnblogs.com/engpj/archive/2023/01/31/{{ url_for(static, filename=css/style.css) }}"> <script src="https://www.cnblogs.com/engpj/archive/2023/01/31/{{ url_for(static, filename=js/my.js) }}"></script> </head> <body> <img src="https://www.cnblogs.com/engpj/archive/2023/01/31/{{ url_for(static, filename=images/air.jpg) }}" alt=""> </body> </html>app.py内容如下。
from flask import Flask, render_template app = Flask(__name__) @app.route(/static) def static_demo(): return render_template(static.html) if __name__ == __main__: app.run()操作MySQL
Python操作MySQL驱动
Flask要想操作数据库 ,必须要先安装Python操作MySQL的驱动 ,在Python中 ,目前有以下MySQL驱动包:
MySQL-python:也就是MySQLdb ,是对C语言操作MySQL数据库的一个简单封装 ,但只支持Python2 。 mysqlclient:是MySQL-python的一个分支 ,支持Python3并且修复了一些bug ,是目前为止执行效率最高的驱动 ,但是安装的时候容易因为环境问题出错 。 pymysql:纯Python实现的驱动 ,执行效率不如mysqlclient,可以和Python代码无缝衔接 。 mysql-connector-python:MySQL官方推出的纯Python连接MySQL驱动 ,执行效率比pymysql慢 。 安装pymysql pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple 安装Flask-SQLAlchemy在Flask中 ,很少会使用pymysql直接写原生SQL语句去操作数据库,更多的是通过SQLAlchemy提供的ORM技术 ,其类似于操作普通Python对象那样来实现对数据库的增删改查 ,而Flask-SQLAlchemy是对SQLAlchemy的一个封装 ,使得在Flask中使用SQLAlchemy更加方便 。Flask-SQLAlchemy需要单独安装 ,因为Flask-SQLAlchemy依赖SQLAlchemy ,所以只要安装了Flask-SQLAlchemy ,SQLAlchemy会自动安装 。
pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simpleSQLAlchemy类似于Jinjia2 ,是可以独立于Flask而被使用的 ,完全可以在任何Python程序中被使用 。SQLAlchemy官方链接
Flask-SQLAlchemy基本使用
连接MySQL使用Flask-SQLAlchemy操作数据库之前 ,需要先创建一个由FLask-SQLAlchemy提供的SQLAlchemy类的对象 ,在创建这个类的时候 ,需要传入当前的app ,然后要在app.config中设置SQLALCHEMY_DATABASE_URI,来配置数据库的连接 。
app.py内容如下 。
from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy from sqlalchemy import text app = Flask(__name__) HOSTNAME = 127.0.0.1 # 主机名 PORT = 3306 # 端口号 USERNAME = root # 连接MySQL的用户名 PASSWORD = 123456 # 连接MySQL的密码 DATABASE = db_flask_test # 在MySQL创建的数据库名称 app.config[SQLALCHEMY_DATABASE_URI] = fmysql+pymysql://{USERNAME}: {PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4 db = SQLAlchemy(app) # 在app.config中设置好连接的数据库信息 ,然后使用SQLAlchemy(app)创建一个db对象 ,QLAlchemy会自动读取app.config中连接数据库的信息 # 测试是否连接成功 with app.app_context(): //应用上下文 with db.engine.connect() as conn: rs = conn.execute(text("select 1")) print(rs.fetchone()) //若打印1,则说明连接成功 @app.route(/) def hello_world(): return render_template(index.html) if __name__ == __main__: app.run() # 运行项目注:测试时若报错 ,提示语句不是可执行的对象 ,可以使用sqlalchemy.text() 函数对语句进行封装 。
ORM模型与表的映射 ORM模型对象关系映射(Object Relationship Mapping) ,简称ORM ,是一种可以用Python面向对象的方式来操作关系型数据库的技术 ,具有可以映射到数据库表能力的Python类我们称之为ORM模型 。一个ORM模型与数据库中一个表相对应 ,ORM模型中的每个类属性分别对应表的每个字段 ,ORM模型的每个实例对象对应表中每条记录 。ORM技术提供了面向对象的SQL交互的桥梁 ,让开发者用面向对象的方式操作数据库 ,使用ORM模型具有以下优势:
开发效率高:几乎不需要写原生SQL语句 ,使用纯Python的方式操作数据库。 安全性高:ORM模型底层代码对一些常见的安全问题 ,比如SQL注入做了防护 ,比直接使用SQL语句更加安全 。 灵活性强:Flask-SQLAlchemy底层支持SQLite 、MySQL 、Oracle 、PostgreSQL等关系型数据库,但针对不同数据库 ,ORM模型代码几乎一模一样 ,只需要修改少量代码,即可完成底层数据库的更换 。 映射方法 法一——通过db.create_all()映射。 with app.app_context(): db.create_all() # 将所有的表同步到数据库中 法二——通过flask-migrate映射 。db.create_all()只能识别新增了哪些模型 ,把新增的模型同步到数据库中 ,若是模型中字段值改变 ,它无法识别 ,这种情况下需要使用flask-migrate 。
安装flask-migrate代码如下 。
pip install flask-migrate -i https://pypi.tuna.tsinghua.edu.cn/simpleflask-migrate三部曲 ,在命令行中执行如下指令 。
flask db init:只执行一次 ,执行后生成migrations文件夹 。 flask db migrate:识别ORM模型的改变 ,生成迁移脚本 。 flask db upgrade:运行迁移脚本 ,同步到数据库中 。 MySQL的增删改查使用ORM进行增删改查操作 ,需要先把操作添加到会话中 ,通过db.session可以获取到会话对象 ,会话对象只是在内存中 ,如果要把会话中的操作提交到数据库中,需要调用db.session.commit()操作 ,如果想要把会话中的操作回滚 ,则可以通过db.session.rollback()实现 。
增加数据使用ORM创建一条数据,首先需使用ORM模型创建一个对象 ,然后添加到会话中 ,再进行commit操作即可 。创建对象时 ,必须要通过关键字参数给字段赋值 。
class User(db.Model): __tablename__ = user id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100), nullable=False) @app.route("/user/add") def add_user(): # 1. 创建ORM对象 user = User(username="张三", password="123456") # sql: insert into user(username, password) values(张三, 123456) # 2. 将ORM对象添加到db.session中 db.session.add(user) # 3. 将db.session中的改变同步到数据库中 db.session.commit() return 用户添加成功 查找数据 class User(db.Model): __tablename__ = user id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100), nullable=False) @app.route("/user/query") def query_user(): # 1. get查找:根据主键查找 user = User.query.get(1) print(f{user.id}-{user.username}-{user.password}) # 2. filter_by查找 ,返回Query数组 users = User.query.filter_by(username=张三) for user in users: print(user.username) return 数据查找成功! 修改数据 class User(db.Model): __tablename__ = user id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100), nullable=False) @app.route("/user/update") def update_user(): user = User.query.filter_by(username=张三).first() user.password = 654321 db.session.commit() return 数据修改成功 删除数据 class User(db.Model): __tablename__ = user id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100), nullable=False) @app.route(/user/delete) def delete_user(): # 1. 查找 user = User.query.get(1) # 2. 从db.session中删除 db.session.delete(user) # 3. 将db.session中的修改同步到数据库中 db.session.commit() return 数据删除成功 ORM模型外键与表的关系关系型数据库中 ,多个表之间可以建立关系 ,表关系总体上可以分成三种 ,分别是:一对一 、一对多(多对一) 、多对多 ,表关系的建立是通过数据库层面的外键来实现的 ,创建外键是通过db.ForeignKey实现的 。
class User(db.Model): __tablename__ = user id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100), nullable=False) articles = db.relationship(Article, back_populates=author) class Article(db.Model): __tablename__ = article id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String(200), nullable=False) content = db.Column(db.Text, nullable=False) author_id = db.Column(db.Integer, db.ForeignKey("user.id")) author = db.relationship(User, back_populates=articles) # author = db.relationship(User, backref=articles), backref会自动给User模型添加一个article属性 ,用来获取文章列表 @app.route("/article/add") def article_add(): article1 = Article(title=Flask学习, content="xxxxx") article1.author = User.query.get(2) article2 = Article(title=Django学习, content=xxxxx) article2.author = User.query.get(2) # 添加到session中 db.session.add_all([article1, article2]) # 同步session中的数据到数据库中 db.session.commit() return 文章添加成功 @app.route(/article/query) def query_article(): user = User.query.get(2) for article in user.articles: print(article.title) return 文章查找成功创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!