翼度科技»论坛 编程开发 python 查看内容

初识Flask

11

主题

11

帖子

33

积分

新手上路

Rank: 1

积分
33
初识Flask

Flask简介

Flask是一个基于Python的web框架,由奥地利开发商Armin Ronacher于2010年4月1日发布。它以灵活、“微”框架著称,其本身并不具备太多的功能,但通过丰富的第三方插件,使其在保持重量轻和简单的同时仍然可以进行高度扩展,让开发者能轻松应对现实开发中复杂的需求。
Flask vs Django



  • Django功能大而全,Flask只包含基本的配置;
  • Flask 比 Django 扩展性更好。
安装Flask

打开cmd窗口,执行如下指令即可安装。
  1. pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
复制代码
执行如下指令查看是否安装成功。
  1. pip list
复制代码
第一个Flask项目(使用Pycharm)

打开PyCharm,选择New Project新建一个项目,之后点击左侧Flask,再选择项目存放路径以及Python解释器路径,点击Create即可。

创建成功后,项目结构如下。
flask_01
│  app.py:项目入口文件。
├─static:存放静态文件(js、css、image等)的文件夹,初始为空。
└─templates:存Jinjia2模板的文件夹,初始为空。

app.py初始内容如下。
  1. from flask import Flask  # 从flask包中导入Flask类
  2. app = Flask(__name__)  # 实例化Flask类
  3. # __name__:代表当前app.py这个模块,其作用为 1.以后出现bug,可以帮助我们快速定位;2.对于寻找模板文件,有一个相对路径
  4. @app.route('/')  # 创建一个路由和视图函数的映射,/代表根路由
  5. def hello_world():  # 当访问根路由时会执行此函数
  6.     return 'Hello World!'
  7. if __name__ == '__main__':
  8.     app.run()  # 运行项目
复制代码
项目配置

debug模式

开启debug模式后,只要修改代码后保存,项目就会重新加载,无需手动重启项目,且开发时如果遇到bug,可以在浏览器上看到出错信息。
设置方法

法一

首先点击Edit Configurations。

勾选FLASK_DEBUG后,点击OK即可。

法二

在app.run()  中添加debug=True。
  1. 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  访问。
  1. @app.route('/home')
  2. def home():
  3.     return 'home'
复制代码
定义有参数的URL

flask里通过来给path指定参数。
参数类型


  • string:字符串类型,可以接受除/以外的字符。

  • int:整型,可以接受能通过int()方法转换的字符。

  • float:浮点型,可以接受能通过float()方法转换的字符。

  • path:路径,类似string,但是中间可以添加/。

  • uuid:UUID类型,UUID是一组32位数的16进制所构成。

  • any:备选值中的任何一个(理解为枚举)。

类型一

敲写下方代码,程序运行后,可通过   127.0.0.1:8888/home/任意数字  访问。
  1. @app.route('/home/<int:user_id>')  # 类型的指定是可选的
  2. def blog_detail(user_id):
  3.     return '您是:%s' % user_id
复制代码

类型二

敲写下方代码,程序运行后,可通过   127.0.0.1:8888/book/list?page=任意数字  访问。
  1. from flask import Flask, request  # 从flask包中导入Flask类
  2. # /book/list:返回第一页的数据
  3. # /book/list?page=2:返回第二页的数据
  4. @app.route('/book/list')
  5. def book_list():
  6.     # arguments: 参数
  7.     # request.args: 类字典类型
  8.     page = request.args.get("page", default=1, type=int)
  9.     return f'您获取的是第{page}页的图书列表'
复制代码

Jinjia2模板

Jinjia2是一个Python模板语言,安装Flask时,Jinjia2会自动安装,Jinjia2模板语言是不分缩进的。
模板渲染

无参数渲染

在templates创建文件index.html。
index.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8.     <h1>这是首页。</h1>
  9. </body>
  10. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def hello_world():
  5.     return render_template('index.html')
  6. if __name__ == '__main__':
  7.     app.run()  # 运行项目
复制代码
有参数渲染

在templates创建文件user_detail.html。
user_detail.html内容如下,Jinjia2通过{}来获取变量的值。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>用户详情</title>
  6. </head>
  7. <body>
  8.     <h1>用户id是{{ user_id }}</h1>
  9. </body>
  10. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/home/<user_id>')
  4. def user_detail(user_id):
  5.     return render_template('user_detail.html', user_id=user_id)
  6. if __name__ == '__main__':
  7.     app.run()  # 运行项目
复制代码
模板访问对象属性

Jinjia2访问对象属性有两种方法,例如{{ user.user_name }}和{{ user['user_name'] }}。
index.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>{{ user.user_name }} + {{ user.user_email }}</h1>
  9. </body>
  10. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. class User:
  4.     def __init__(self, user_name, user_email):
  5.         self.user_name = user_name
  6.         self.user_email = user_email
  7. @app.route('/')
  8. def hello_world():
  9.     user = User("lili", '123456@qq.com')
  10.     return render_template('index.html', user=user)
  11. if __name__ == '__main__':
  12.     app.run()
复制代码
过滤器

在Python中,如果需要对某个变量进行处理,可以通过函数来实现;在模板中,则是通过过滤器来实现的。过滤器本质上也是函数,在模板中使用管道符号(|)来调用。例如有字符串类型变量name,想要获取它的长度,可以通过{{name | length}}来获取,length是Jinjia2内置的过滤器,Jinjia2会把name当做第一个参数传给length过滤器底层对应的函数。
内置过滤器

filter.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>filter_demo</title>
  6. </head>
  7. <body>
  8.     名字:{{ user.user_name }}
  9.     名字长度:{{ user.user_name|length }}
  10. </body>
  11. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. class User:
  4.     def __init__(self, user_name, user_email):
  5.         self.user_name = user_name
  6.         self.user_email = user_email
  7. @app.route('/filter')
  8. def filte_page():
  9.     user = User('lili', '123@qq.com')
  10.     return render_template('filter.html', user=user)
  11. if __name__ == '__main__':
  12.     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内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>filter_demo</title>
  6. </head>
  7. <body>
  8.     时间:{{ my_time|d_format }}
  9. </body>
  10. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. from datetime import datetime
  3. app = Flask(__name__)
  4. @app.route('/filter')
  5. def filte_page():
  6.     my_time = datetime.now()
  7.     return render_template('filter.html', my_time=my_time)
  8. def date_format(value, format="%Y-%m-%d %H:%M"):
  9.     return value.strftime(format)
  10. app.add_template_filter(date_format, 'd_format')
  11. if __name__ == '__main__':
  12.     app.run()
复制代码
控制语句

if语句

filter.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>filter_demo</title>
  6. </head>
  7. <body>
  8.     {% if age > 18 %}
  9.         您已满18岁
  10.     {% elif age == 18 %}
  11.         您刚满18岁
  12.     {% else %}
  13.         您未满18岁
  14.     {% endif %}
  15. </body>
  16. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/filter')
  4. def filte_page():
  5.     age = 17
  6.     return render_template('filter.html', age=age)
  7. if __name__ == '__main__':
  8.     app.run()
复制代码
for循环

Jinjia2中的for循环没有break语句。
filter.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>filter_demo</title>
  6. </head>
  7. <body>
  8.     {% for student in students %}
  9.         学生姓名:{{ student.name }},学生年龄:{{ student.age }}
  10.     {% endfor %}
  11. </body>
  12. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/filter')
  4. def filte_page():
  5.     students = [
  6.         {'name':'lili', 'age':18},
  7.         {'name':'lucy', 'age':17},
  8.         {'name':'lfiv', 'age':19}
  9.     ]
  10.     return render_template('filter.html', students=students)
  11. if __name__ == '__main__':
  12.     app.run()  # 运行项目
复制代码
模板继承

一个网站中,大部分网页的模块是重复的,比如顶部的导航栏、底部的备案信息等,如果在每个页面中都重复地去写这些代码,会让项目变得臃肿,提高后期维护成本。此时,可以通过模板继承,把一些重复性的代码写在父模板里,子模板继承父模板后,再分别实现自己的代码。
父模板文件base.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>{% block title %}{% endblock %}</title>
  6. </head>
  7. <body>
  8. <ul>
  9.     <li><a target="_blank" href="https://www.cnblogs.com/#">首页</a></li>
  10.     <li><a target="_blank" href="https://www.cnblogs.com/#">新闻</a></li>
  11. </ul>
  12. {% block body %}
  13. {% endblock %}
  14. <footer>底部标签</footer>
  15. </body>
  16. </html>
复制代码
child1.html内容如下。
  1. {% extends 'base.html' %}
  2. {% block title %}
  3.     我是子模板
  4. {% endblock %}
  5. {% block body %}
  6.     我是子模板的文字
  7. {% endblock %}
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/child1')
  4. def child1():
  5.     return render_template('child1.html')
  6. if __name__ == '__main__':
  7.     app.run()
复制代码
加载静态文件

static.html内容如下。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>static_demo</title>
  6.     <link rel="stylesheet" href="https://www.cnblogs.com/{{ url_for('static', filename='css/style.css') }}">
  7.    
  8. </head>
  9. <body>
  10.     <img src="https://www.cnblogs.com/{{ url_for('static', filename='images/air.jpg') }}" alt="">
  11. </body>
  12. </html>
复制代码
app.py内容如下。
  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/static')
  4. def static_demo():
  5.     return render_template('static.html')
  6. if __name__ == '__main__':
  7.     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

  1. 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会自动安装。
  1. pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
复制代码
SQLAlchemy类似于Jinjia2,是可以独立于Flask而被使用的,完全可以在任何Python程序中被使用。SQLAlchemy官方链接
Flask-SQLAlchemy基本使用

连接MySQL

使用Flask-SQLAlchemy操作数据库之前,需要先创建一个由FLask-SQLAlchemy提供的SQLAlchemy类的对象,在创建这个类的时候,需要传入当前的app,然后要在app.config中设置SQLALCHEMY_DATABASE_URI,来配置数据库的连接。
app.py内容如下。
  1. from flask import Flask, render_template
  2. from flask_sqlalchemy import SQLAlchemy
  3. from sqlalchemy import text
  4. app = Flask(__name__)
  5. HOSTNAME = '127.0.0.1'  # 主机名
  6. PORT = 3306  # 端口号
  7. USERNAME = 'root'  # 连接MySQL的用户名
  8. PASSWORD = '123456'  # 连接MySQL的密码
  9. DATABASE = 'db_flask_test'  # 在MySQL创建的数据库名称
  10. app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:                     {PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'
  11. db = SQLAlchemy(app)
  12. # 在app.config中设置好连接的数据库信息,然后使用SQLAlchemy(app)创建一个db对象,QLAlchemy会自动读取app.config中连接数据库的信息
  13. # 测试是否连接成功
  14. with app.app_context():  //应用上下文
  15.     with db.engine.connect() as conn:
  16.         rs = conn.execute(text("select 1"))
  17.         print(rs.fetchone())  //若打印1,则说明连接成功
  18. @app.route('/')
  19. def hello_world():
  20.     return render_template('index.html')
  21. if __name__ == '__main__':
  22.     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()映射。

  1. with app.app_context():
  2.     db.create_all()  # 将所有的表同步到数据库中
复制代码
法二——通过flask-migrate映射。

db.create_all()只能识别新增了哪些模型,把新增的模型同步到数据库中,若是模型中字段值改变,它无法识别,这种情况下需要使用flask-migrate。
安装flask-migrate代码如下。
  1. pip install flask-migrate -i https://pypi.tuna.tsinghua.edu.cn/simple
复制代码
flask-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操作即可。创建对象时,必须要通过关键字参数给字段赋值。
  1. class User(db.Model):
  2.     __tablename__ = 'user'
  3.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  4.     username = db.Column(db.String(100), nullable=False)
  5.     password = db.Column(db.String(100), nullable=False)
  6. @app.route("/user/add")
  7. def add_user():
  8.     # 1. 创建ORM对象
  9.     user = User(username="张三", password="123456")  
  10.     # sql: insert into user(username, password) values('张三', '123456')
  11.     # 2. 将ORM对象添加到db.session中
  12.     db.session.add(user)
  13.     # 3. 将db.session中的改变同步到数据库中
  14.     db.session.commit()
  15.     return '用户添加成功'
复制代码
查找数据

  1. class User(db.Model):
  2.     __tablename__ = 'user'
  3.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  4.     username = db.Column(db.String(100), nullable=False)
  5.     password = db.Column(db.String(100), nullable=False)
  6. @app.route("/user/query")
  7. def query_user():
  8.     # 1. get查找:根据主键查找
  9.     user = User.query.get(1)
  10.     print(f'{user.id}-{user.username}-{user.password}')
  11.     # 2. filter_by查找,返回Query数组
  12.     users = User.query.filter_by(username='张三')
  13.     for user in users:
  14.         print(user.username)
  15.     return '数据查找成功!'
复制代码
修改数据

  1. class User(db.Model):
  2.     __tablename__ = 'user'
  3.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  4.     username = db.Column(db.String(100), nullable=False)
  5.     password = db.Column(db.String(100), nullable=False)
  6. @app.route("/user/update")
  7. def update_user():
  8.     user = User.query.filter_by(username='张三').first()
  9.     user.password = '654321'
  10.     db.session.commit()
  11.     return '数据修改成功'
复制代码
删除数据

  1. class User(db.Model):
  2.     __tablename__ = 'user'
  3.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  4.     username = db.Column(db.String(100), nullable=False)
  5.     password = db.Column(db.String(100), nullable=False)
  6. @app.route('/user/delete')
  7. def delete_user():
  8.     # 1. 查找
  9.     user = User.query.get(1)
  10.     # 2. 从db.session中删除
  11.     db.session.delete(user)
  12.     # 3. 将db.session中的修改同步到数据库中
  13.     db.session.commit()
  14.     return '数据删除成功'
复制代码
ORM模型外键与表的关系

关系型数据库中,多个表之间可以建立关系,表关系总体上可以分成三种,分别是:一对一、一对多(多对一)、多对多,表关系的建立是通过数据库层面的外键来实现的,创建外键是通过db.ForeignKey实现的。
  1. class User(db.Model):
  2.     __tablename__ = 'user'
  3.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  4.     username = db.Column(db.String(100), nullable=False)
  5.     password = db.Column(db.String(100), nullable=False)
  6.     articles = db.relationship('Article', back_populates='author')
  7. class Article(db.Model):
  8.     __tablename__ = 'article'
  9.     id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  10.     title = db.Column(db.String(200), nullable=False)
  11.     content = db.Column(db.Text, nullable=False)
  12.     author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
  13.     author = db.relationship('User', back_populates='articles')
  14.     # author = db.relationship('User', backref='articles'), backref会自动给User模型添加一个article属性,用来获取文章列表
  15. @app.route("/article/add")
  16. def article_add():
  17.     article1 = Article(title='Flask学习', content="xxxxx")
  18.     article1.author = User.query.get(2)
  19.     article2 = Article(title='Django学习', content='xxxxx')
  20.     article2.author = User.query.get(2)
  21.     # 添加到session中
  22.     db.session.add_all([article1, article2])
  23.     # 同步session中的数据到数据库中
  24.     db.session.commit()
  25.     return '文章添加成功'
  26. @app.route('/article/query')
  27. def query_article():
  28.     user = User.query.get(2)
  29.     for article in user.articles:
  30.         print(article.title)
  31.     return '文章查找成功'
复制代码
来源:https://www.cnblogs.com/engpj/p/17081086.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具