Flask 框架是 Python 开发的一个基于 Werkzeug 和 Jinja 2 的 web 开发微框架, 它的优势就是极其简洁, 但又非常灵活, 而且容易学习和应用. 因此 Flask 框架是 Python 新手快速开始 Web 开发最好的选择, 此外, 使用 Flask 框架的另一个好处在于你可以非常轻松地将基于 Python 的机器学习算法或数据分析算法集成到 Web 应用中.
如果希望深入学习 Flask Web 开发, 推荐这个教程:
深入浅出 Flask
1, 可以用 Flask 框架做什么
从博客应用到克隆一个 Facebook 或者 Twitter, 理论上你可以用 Flask 做任何事情. 有很多库可以直接使用, 例如 flask-sockets,flask-google-maps 等, 而且 Flask 框架支持 MySQL,PostgreSQL,MongoDB 等诸多数据库.
我能想到的一些可以用 Flask 框架实现的 Web 应用类型: 博客应用, 聊天应用, 仪表盘应用, RESTAPI, 管理页面, 邮件服务等.
安装 Flask
使用 pip 安装 Flask:
- $ pip install flask
- 2,Hello,World
创建一个文件 App.py, 然后只需要几个简单的步骤, 就可以写出 Flask 版本的 Hello World
引入 Flask 类
from flask import Flask
创建 Flask 对象, 我们将使用该对象进行应用的配置和运行:
App = Flask(__name__)
name 是 Python 中的特殊变量, 如果文件作为主程序执行, 那么__name__变量的值就是__main__, 如果是被其他模块引入, 那么__name__的值就是模块名称.
编写主程序
在主程序中, 执行 run() 来启动应用:
- if __name__ =="__main__":
- App.run(debug=True, port=8080)
改名启动一个本地服务器, 默认情况下其地址是 localhost:5000, 在上面的代码中, 我们使用关键字参数 port 将监听端口修改为 8080.
路由
使用 App 变量的 route() 装饰器来告诉 Flask 框架 URL 如何触发我们的视图函数:
- @App.route('/')
- def hello_world():
- return 'Hello, World!'
上面的标识, 对路径'/'的请求, 将转为对 hello_world() 函数的调用. 很直白, 对吧?
运行
现在, 让我们完整地看一下 App.py 的整个代码:
- from flask import Flask
- App = Flask(__name__)
- @App.route('/')
- def hello_world():
- return 'Hello, World!'
- if __name__ =="__main__":
- App.run(debug=True,port=8080)
然后运行起来:
$ python App.py
你应该会看到如下输入:
- * Serving Flask App "app" (lazy loading)
- * Environment: production
- * Debug mode: on
- * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
- * Restarting with stat
- * Debugger is active!
- * Debugger PIN: 770-937-705
现在就可以打开浏览器访问 http://127.0.0.1:8080 / 了:
3, 使用 html 模板
首先我们看看如何原始的 HTML 代码插入 Flask 应用:
- from flask import Flask
- App = Flask(__name__)
- @App.route('/greet')
- def greet():
- user = {'username': 'John', 'age': "20"}
- return '''
- <html>
- <head>
- <title>Templating</title>
- </head>
- <body>
- <h1>Hello, '''+ user['username'] +'''!, you're''' + user['age'] + ''' years old.</h1>
- </body>
- </html>'''if __name__ =='__main__':
- App.run(debug = True,port=8080)
在上面的代码中, 我们使用拼接的 HTML 字符串来展示 user 字典的数据. 现在访问 http://127.0.0.1:8080/greet:
拼接 HTML 字符串非常容易出错, 因此 Flask 使用 Jinja 2 模板引擎来分离数据逻辑和展示层.
我们将模板文件按如下路径放置:
Apps folder
/App.py
- templates
- |-/index.HTML
使用模板时, 视图函数应当返回 render_template() 的调用结果. 例如下面的代码片段渲染模板 index.HTML, 并将渲染结果作为视图函数的返回值:
- from flask import Flask, render_template
- App = Flask(__name__)
- @App.route('/hello')
- def hello():
- return render_template('index.html', name="Alex")
- if __name__ == '__main__':
- App.run(debug = True)
在上面的代码中, 模板文件 index.HTML 依赖于变量 name, 其内容如下:
- <HTML>
- <body>
- {% if name %}
- <h2>Hello {{ name }}.</h2>
- {% else %}
- <h2>Hello.</h2>
- {% endif %}
- </body>
- </HTML>
模板文件的语法扩充了 HTML, 因此可以使用变量和逻辑.
在浏览器中访问 http://127.0.0.1:8080/hello/alex:
4, 使用表单
每个 Web 应用都需要使用表单来采集用户数据. 现在让我们使用 Flask 框架创建一个简单的表单来收集用户的基本信息, 例如名称, 年龄, 邮件, 兴趣爱好等, 我们将这个模板文件命名为 bio_form.HTML
- <!DOCTYPE HTML>
- <HTML>
- <head>
- <title>
- </title>
- </head>
- <body>
- <h1>
- Bio Data Form
- </h1>
- <form action="showbio">
- <label>
- Username
- </label>
- <input type="name" name="username">
- <br>
- <label>
- </label>
- <input type="email" name="email">
- <br>
- <label>
- Hobbies
- </label>
- <input type="name" name="hobbies">
- <br>
- <input type="submit" name="">
- </form>
- </body>
- </HTML>
视图函数 bio_data_form 同时支持 POST 和 GET 请求. GET 请求将渲染 bio_form.HTML 模板, 而 POST 请求将重定向到 showbio:
- @App.route('/form', methods=['POST', 'GET'])
- def bio_data_form():
- if request.method == "POST":
- username = request.form['username']
- age = request.form['age']
- email = request.form['email']
- hobbies = request.form['hobbies']
- return redirect(url_for('showbio',
- username=username,
- age=age,
- email=email,
- hobbies=hobbies))
- return render_template("bio_form.html")
下面是 showbio 的实现:
- @App.route('/showbio', methods=['GET'])
- def showbio():
- username = request.args.get('username')
- age = request.args.get('age')
- email = request.args.get('email')
- hobbies = request.args.get('hobbies')
- return render_template("show_bio.html",
- username=username,
- age=age,
- email=email,
- hobbies=hobbies)
以及 show_bio.HTML 的内容:
- <!DOCTYPE HTML>
- <HTML>
- <head>
- <title>
- Bio-Data Details
- </title>
- </head>
- <body>
- <h1>
- Bio-Data Details
- </h1>
- <hr>
- <h1>
- Username: {{ username }}
- </h1>
- <h1>
- Email: {{ email }}
- </h1>
- <h1>
- Hobbies: {{ hobbies }}
- </h1>
- </body>
- </HTML>
5, 数据库集成: 使用 SQLAlchemy
Flask 不能直接连接数据库, 需要借助于 ORM(Object Relational Mapper). 在这一部分, 我们将借助于 SQLAlchemy 使用 Postgres 数据库.
安装 Flask-SQLAlchemy 和 Postgres
首先安装 flask-sqlalchemy:
$ pip install flask-sqlalchemy
然后从官方下载并安装 postgres:https://postgresapp.com/
创建数据库
在终端中使用下面的命令创建一个 appdb 数据库:
$ createdb appdb
更新应用配置
修改 App.config, 添加数据库相关的配置信息:
- App.config['DEBUG'] = True
- App.config['SQLALCHEMY_DATABASE_URI']='postgresql://localhost/appdb'
- SQLALCHEMY_TRACK_MODIFICATIONS = True
- db = SQLAlchemy(App)
然后在代码中就可以使用这些配置数据了:
- from flask import Flask, request, render_template
- from flask_sqlalchemy import SQLAlchemy
- # Settings
- App = Flask(__name__)
- App.config['DEBUG'] = True
- App.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/appdb'
- db = SQLAlchemy(App)
- @App.route('/')
- def hello_world():
- return 'Hello, World!'
- if __name__ == '__main__':
- App.run()
现在, 让我们创建第一个模型 (Model). 所有模型的基类是 db.Model, 使用 Column 来定义数据列:
- class Post(db.Model):
- id = db.Column(db.Integer(), primary_key=True)
- title = db.Column(db.String(80), unique=True)
- post_text = db.Column(db.String(255))
- def __init__(self, title, post_text):
- self.title = title
- self.post_text = post_text
在代码中使用模型:
- from flask import Flask
- from flask_sqlalchemy import SQLAlchemy
- App = Flask(__name__)
- App.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/testdb'
- db = SQLAlchemy(App)
- class Post(db.Model):
- id = db.Column(db.Integer(), primary_key=True)
- title = db.Column(db.String(80), unique=True)
- post_text = db.Column(db.String(255))
- def __init__(self, title, post_text):
- self.title = title
- self.post_text = post_text
- @App.route('/')
- def index():
- return "Hello World"
- App = Flask(__name__)
- if __name__ == "__main__":
- App.run()
6, 模型 - 数据同步
使用 ORM 时, 需要执行迁移操作以便在模型和持久化数据之间保持同步. 我们使用 Flask-Migrate 这个扩展来完成该任务.
首先安装:
- $ pip install flask-migrate
- $ pip install flask_script
然后在代码中引入:
- from flask_script import Manager
- from flask_migrate import Migrate, MigrateCommand
进行必要的配置:
- migrate = Migrate(App, db)
- manager = Manager(App)
- manager.add_command('db', MigrateCommand)
运行管理器:
- if __name__ == '__main__':
- manager.run()
完整的代码如下:
- from flask import Flask
- from flask_sqlalchemy import SQLAlchemy
- from flask_script import Manager
- from flask_migrate import Migrate, MigrateCommand
- App = Flask(__name__)
- App.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/appdb'
- db = SQLAlchemy(App)
- migrate = Migrate(App, db)
- manager = Manager(App)
- manager.add_command('db', MigrateCommand)
- class Post(db.Model):
- id = db.Column(db.Integer(), primary_key=True)
- title = db.Column(db.String(80), unique=True)
- post_text = db.Column(db.String(255))
- def __init__(self, title, post_text):
- self.title = title
- self.post_text = post_text
- @App.route('/')
- def index():
- return "Hello World"
- if __name__ == "__main__":
- manager.run()
使用如下的命令初始化 Alembic:
- $ python App.py db init
- Creating directory /Users/Vihar/Desktop/flask-databases/migrations ... done
- ...
- ...
- ...
- Generating /Users/Vihar/Desktop/flask-databases/migrations/alembic.INI ... done
执行第一个迁移任务:
- $ python App.py db migrate
- INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
- INFO [alembic.runtime.migration] Will assume transactional DDL.
- INFO [alembic.autogenerate.compare] Detected added table 'post'
- Generating /Users/Vihar/Desktop/flask-databases/migrations/versions/ed3b3a028447_.py ... done
一旦上述命令执行完毕, 我们的数据表就会创建成功. 现在更新数据库:
$ python App.py db upgrade
来源: https://www.cnblogs.com/mailer/p/10100625.html