Python Flask快速入门
一、Python基础
1.python基础
if __name__ == '__main__': # 判断是否是主程序print("hello word!")
为什么使用?判断当前模块是否作为主程序运行,而不是被其他模块导入使用。
2.Python3基础知识温习
Number 数字
String 字符串
List 列表
Tuple 元祖
Set 集合
Dictionary 字典
二、Flask框架简介
1.常见MVC框架对比讲解
- Django 全能框架、学习成本较大
- Flask 微框架、易学习、Jinja2模板、内置服务器、扩展丰富,易扩展
- Tornado 高性能、异步处理、扩展不多
- Bottle 小巧、
2. Flask框架安装
pip install Flask
pip install -r requirements.txt
# Python 3.7.16
Flask==2.2.5
3.快速体验Flask Hello World
from flask import Flaskapp = Flask(__name__)@app.route("/")
def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run(host='0.0.0.0', port=80, debug=True) # 启动
4.Flask为什么可以独立运行
- Werkzeug 是一个WSGI工具包,也可以作为一个Web框架的底层库
Werkzeug
from http.client import responsesfrom werkzeug.wrappers import Response,Requestclass Shortly(object):def __call__(self, environ, start_response):# start_response('200 OK', [('Content-Type', 'text/html')])# return [b'Hello World!']request= Request(environ)text ="hello Word~~, %s"%(request.args.get('a','5656'))responses=Response(text, mimetype='text/html')return responses(environ, start_response)if __name__ == '__main__':from werkzeug.serving import run_simpleapp=Shortly()run_simple('localhost', 9000, app)
CGI FastCGI WSGI UWSGI
- CGI(Common Gateway Inteface):通用网关接口是一种重要的互联网技术,可以让一个客户端,从网页浏览器向执心在网络服务器上的程序请求数据。CGI描述了服务器和请求处理程序之间传输数据的一种标准。定义了客户端服务器之间如何传数据。
- FastCGI:快速通用网关接口(Fast Common Gateway Interface)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。FastCGI致力于减少网页服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的网页请求。我们常见的Nginx、Apache都有实现该协议
- WSGI:Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。为Python定义的web服务器和web框架之间的接口标准。
- uWSGI:一个Web Server,即一个实现了WSGI的服务器。
- uwsgi:是uWSGI服务器实现的独有的协议。
5.Flask配置
-
网络配置:app.run()和 app.run(host = 0.0.0.0)
-
127.0.0.1 和0.0.0.0的区别
from flask import Flask app = Flask(__name__)@app.route("/") def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run() # 启动 127.0.0.1 只运行本机访问app.run(host='0.0.0.0') # 启动 0.0.0.0 可以远程访问
Flask配置加载方式–变量配置
from flask import Flaskapp = Flask(__name__)
# 变量的配置
app.config['DEBUG'] =True@app.route("/")
def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run(host='0.0.0.0') # 启动* Serving Flask app '4-5-1'
* Debug mode: on* Serving Flask app '4-5-1'
* Debug mode: off
Flask 配置加载方式–模块配置
from flask import Flaskapp = Flask(__name__)
app.config.from_object('config.base_setting')
@app.route("/")
def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run(host='0.0.0.0') # 启动
Flask配置加载方式–环境变量配置
from flask import Flaskapp = Flask(__name__)
app.config.from_envvar("ops_config")
@app.route("/")
def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run(host='0.0.0.0') # 启动
Linux主机:export ops-config=本地配置文件地址
Windows主机:set ops-config=本地配置文件地址
Flask 配置加载方式–文件配置
from flask import Flaskapp = Flask(__name__)
app.config.from_pyfile("config/base_setting.py")
@app.route("/")
def hello():return "hello, I Love Imooc"if __name__ == '__main__':app.run(host='0.0.0.0') # 启动
三、Flask路由和请求对象
1.Flask 路由注册
- app.route 和 app.add_url_rule 和蓝图
@app.route
from flask import Flaskapp=Flask(__name__)@app.route('/')
def hello():return 'hello, I Love Imooc'# user_name 路径参数
@app.route('/my/<user_name>')
def my(user_name):return 'hello, myPage!'+user_nameif __name__ == '__main__':app.run(debug=True)
app.add_url_rule
from flask import Flask
app=Flask(__name__)def hello():return 'hello, I Love Imooc'def my(user_name):return 'hello, myPage!'+user_nameapp.add_url_rule('/',view_func=hello)
app.add_url_rule('/my/<user_name>',view_func=my) # user_name 路径参数if __name__ == '__main__':app.run(debug=True)
路由注册-蓝图
from flask import Flask, Blueprintapp = Flask(__name__)
index_page = Blueprint("index_page", __name__)@index_page.route("/")
def index_page_index():return "index_page_index"app.register_blueprint(index_page, url_prefix="/imooc")if __name__ == '__main__':app.run("0.0.0.0",debug=True)
蓝图分层
application.py
程序的启动入口
from flask import Flask, Blueprint
from indexController import index_page
'''
post/index 列表
post/info 详情
post/set 添加|编辑
post/ops 操作(删除|恢复)
'''
app = Flask(__name__)app.register_blueprint(index_page, url_prefix="/index")if __name__ == '__main__':app.run("0.0.0.0",debug=True)
indexController.py
程序动作
from flask import Blueprintindex_page = Blueprint("index_page", __name__)@index_page.route("/")
def index_page_index():return "index_page_index"@index_page.route("/my")
def index_page_my():return "Imooc"
2.解读HTTP请求流程
3.获取请求对象的GET和POST参数
# GET 请求示例:获取查询参数
# 示例 URL: http://127.0.0.1:5000/index/get?a=123
@index_page.route("/get")
def get():# 获取请求参数 a,默认值为 'I love imooc'var_a = request.args.get('a', 'I love imooc')# 返回信息展示请求方法、完整参数字典、以及提取的变量return "request:%s, params:%s, var_a:%s" % (request.method, request.args, var_a)
# GET 请求示例:获取多个查询参数
# 示例 URL: http://127.0.0.1:5000/index/to?a=456&b=789
@index_page.route("/to")
def to():# 获取参数 a 和 b 的值var_a = request.args.get('a')var_b = request.args.get('b')return "request:%s, params:%s, var_a:%s , var_b:%s" % (request.method, request.args, var_a, var_b)
# POST 请求示例:接收表单数据
# 使用工具如 Postman 发送 POST 请求:
# URL: http://127.0.0.1:5000/index/post
# Body: x-www-form-urlencoded 类型,包含 a 和 b 字段
@index_page.route("/post", methods=['POST'])
def post():var_a = request.form.get('a')var_b = request.form.get('b')return "request:%s, params:%s, var_a:%s , var_b:%s" % (request.method, request.args, var_a, var_b)
# POST 请求示例:通用方式获取参数(支持 form-data 和 query string)
# 适用于 GET/POST 等多种请求类型
# URL: http://127.0.0.1:5000/index/value
@index_page.route("/value", methods=['POST'])
def value():req = request.values # 合并了 args 和 formvar_a = req.get('a')var_b = req.get('b')return "req:%s , var_a:%s , var_b=%s" % (req, var_a, var_b)
# 文件上传接口
# 使用工具发送 POST 请求:
# URL: http://127.0.0.1:5000/index/upload
# Body: form-data 类型,键值对中一个字段为文件类型
@index_page.route("/upload", methods=['POST'])
def upload():# 获取上传的文件对象req = request.filesreturn "req:%s" % req
四、Flask Response和Jinja2
1.Flask响应请求
text/html
# ======================================
# 返回纯文本(text/plain)
# 示例 URL: http://127.0.0.1:5000/index/text
# ======================================
@index_page.route("/text")
def text():# 默认返回字符串时,Flask 会自动设置 Content-Type 为 'text/html'return "text/html"# ======================================
# 返回纯文本并显式指定状态码和响应对象
# 示例 URL: http://127.0.0.1:5000/index/text_same
# ======================================
@index_page.route("/text_same")
def text_same():# 使用 make_response 构造响应对象,并指定状态码 200response = make_response("text/html", 200)return response
Json
# ======================================
# 返回 JSON 格式数据(手动设置 Content-Type)
# 示例 URL: http://127.0.0.1:5000/index/json
# ======================================
@index_page.route("/json")
def json():# 定义一个字典类型的数据结构data = {"name": "xiaoming","age": 18}# 将字典转换为 JSON 字符串response = make_response(data.dumps())# 显式设置响应头中的 Content-Type 为 application/jsonresponse.headers["Content-Type"] = "application/json"return response# ======================================
# 返回 JSON 格式数据(使用 jsonify 工具函数)
# 示例 URL: http://127.0.0.1:5000/index/json_same
# ======================================
@index_page.route("/json_same")
def json_same():data = {"name": "xiaoming","age": 18}# jsonify 自动将字典转换为 JSON 响应,并设置正确的 Content-Typeresponse = make_response(jsonify(data))return response
模板响应 templates/index.html
# ======================================
# 渲染 HTML 模板
# 示例 URL: http://127.0.0.1:5000/index/template
# 要求:项目中需有 templates/index.html 文件
# ======================================
@index_page.route("/template")
def template():# 使用 render_template 加载并渲染模板文件 index.htmlreturn render_template("index.html")
2.模板引擎Jinja2
传递变量
-
直接传参
@index_page.route("/template") def template():name = 'xiaoming'# 向模板 index.html 传递变量 namereturn render_template("index.html", name=name)
-
使用字典解包传参(context)
@index_page.route("/context") def context():context = {"name": "xiaoming","age": 18,"hobbies": ["reading", "coding", "sports"]}# 使用 **context 解包字典传参return render_template("index.html", **context)
-
templates/index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Flask Template Example</title> </head> <body><h1>Hello, {{ name }}!</h1>{% if age %}<p>Your age is: {{ age }}</p>{% endif %}{% if hobbies %}<ul><li>{{ hobbies[0] }}</li><li>{{ hobbies[1] }}</li><li>{{ hobbies[2] }}</li></ul>{% endif %} </body> </html>
Jinja2基本语法
-
条件判断
{% if %}
templates/user_profile.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>User Profile</title> </head> <body><h1>用户信息</h1>{% if name %}<p>姓名: {{ name }}</p>{% else %}<p>未提供姓名</p>{% endif %}{% if age %}<p>年龄: {{ age }}</p>{% endif %}{% if hobbies %}<h3>兴趣爱好:</h3><ul>{% for hobby in hobbies %}<li>{{ hobby }}</li>{% endfor %}</ul>{% else %}<p>暂无兴趣爱好</p>{% endif %}</body> </html>
@index_page.route("/user") def user():context = {"name": "小明","age": 20,"hobbies": ["编程", "读书", "运动"]}return render_template("user_profile.html", **context)
-
循环
{% for %}
上面的例子已经包含了循环的用法。你可以看到 Jinja2 支持 Python 风格的for
循环。{% for user in users %}<div>ID: {{ user.id }}, Name: {{ user.name }},Email: {{ user.email }}</div> {% else %}<p>没有用户数据</p> {% endfor %}
-
模板继承
{% extends %}
,{% block %}
判断Jinja中最强大的部分就是模板继承。模板继承允许你构建一个包含你站点共同元素的基本模板“骨架”,并定义子模板可以覆盖的块。听起来复杂,实际上很简单
templates/base.html
<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><title>{% block title %}默认标题{% endblock %}</title> </head> <body><header><h1>我的网站</h1><nav><a href="/">首页</a> |<a href="/user">用户页</a></nav></header><main>{% block content %}默认内容区域{% endblock %}</main><footer><p>© 2025 我的公司</p></footer></body> </html>
子模板:
templates/index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>{{name}}</title> </head> <body> {% extends "base.html" %}{% block title %}首页 {% endblock %}{% block content %}<h2>欢迎来到首页</h2><p>这是继承自 base.html 的页面。</p> {% endblock %} </body> </html>
@index_page.route("/index") def index():return render_template("index.html")
🧩 Jinja2 其他常用语法(补充)
语法 说明 {{ variable }}
输出变量 {% expression %}
控制逻辑(如 if, for) {# 注释 #}
模板注释,不会输出到 HTML 中 {{ 'hello'
upper }}` {{ now() }}
调用函数(需在 Flask 中注册)
五、Flask 数据库ORM
1.SQLAlchemy数据库通讯
Flask-SQLAlchemy
pip install flask_sqlalchemy
pip install mysqlclient
- 使用windows10,终端pip install mysqlclient,可能安装不了mysqlclient这个库的,需要在https://pypi.org/project/mysqlclient/#files中下载相应系统的whl文件。然后pip install下载的whl文件
- 使用pymysql:pip install pymysql
配置数据库URI
from flask import Flask
from indexController import index_page
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# 数据库 URI
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:yanpeng2580@127.0.0.1/mysql"
# 可选:关闭追踪修改,节省资源
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 注册蓝图
app.register_blueprint(index_page, url_prefix="/index")
# 初始化 SQLAlchemy
db = SQLAlchemy(app)if __name__ == '__main__':app.run("0.0.0.0", debug=True)
@post_page.route("/index")
def index():context = {"name": "xiaoming"}context['yser'] = [{"name": "xiaoming", "age": 18},{"name": "xiaoming", "age": 18},{"name": "xiaoming", "age": 18}]context['num_list'] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]sql = text("SELECT * FROM `user`")result = db.session.execute(sql) # 推荐使用 session 执行 SQLfor row in result:print(row)context['result'] = resultreturn render_template("db.html", **context)
2.Model访问数据库
from application import db
class User(db.Model):__tablename__ = 'user'Host = db.Column(db.String(80), primary_key=True)User = db.Column(db.String(120), primary_key=True)
@post_page.route("/index")
def index():context = {"name": "xiaoming"}result = User.query.all()for row in result:print(row)context['result'] = resultreturn render_template("db.html", **context)
3.自动生成Model
flask-sqlacodegen
pip install flask-sqlacodegen
flask-sqlacodegen 'mysql://root:yanpeng2580@127.0.0.1/mysql' --tables user --outfile "common/models/user.py" --flask
# coding: utf-8
from application import dbclass SysUser(db.Model):__tablename__ = 'sys_user'user_id = db.Column(db.BigInteger, primary_key=True, info='??ID')dept_id = db.Column(db.BigInteger, info='??ID')user_name = db.Column(db.String(30), nullable=False, info='????')nick_name = db.Column(db.String(30), nullable=False, info='????')user_type = db.Column(db.String(2), server_default=db.FetchedValue(), info='?????00?????')email = db.Column(db.String(50), server_default=db.FetchedValue(), info='????')phonenumber = db.Column(db.String(11), server_default=db.FetchedValue(), info='????')sex = db.Column(db.String(1), server_default=db.FetchedValue(), info='?????1? 2? 0???')avatar = db.Column(db.String(100), server_default=db.FetchedValue(), info='????')password = db.Column(db.String(100), server_default=db.FetchedValue(), info='??')cleartext = db.Column(db.String(100), server_default=db.FetchedValue(), info='????')status = db.Column(db.String(1), server_default=db.FetchedValue(), info='?????0?? 1???')del_flag = db.Column(db.String(1), server_default=db.FetchedValue(), info='?????0???? 2?????')login_ip = db.Column(db.String(128), server_default=db.FetchedValue(), info='????IP')login_date = db.Column(db.DateTime, info='??????')create_by = db.Column(db.String(64), server_default=db.FetchedValue(), info='???')create_time = db.Column(db.DateTime, info='????')update_by = db.Column(db.String(64), server_default=db.FetchedValue(), info='???')update_time = db.Column(db.DateTime, info='????')remark = db.Column(db.String(500), info='??')
from flask import Blueprint, make_response, jsonify
from gen.model.sys_user import SysUser
post_page = Blueprint("post_page", __name__)@post_page.route("/index")
def index():result = SysUser.query.all()# response = make_response(jsonify(result))for item in result:print(item.user_id, item.user_name, item.nick_name)return "ok"
五、构建MVC框架
1.构建MVC
2.MVC 优化
-
多环境配置文件:测试环境/开发环境/本地环境等
使用yml
pip install pyyaml
application.py
import os import yaml from flask import Flask from flask_sqlalchemy import SQLAlchemy# 设置当前运行环境(你可以根据需要手动修改这个值) CURRENT_ENV = 'development' # 可选:'development', 'testing', 'production'# 加载配置 def load_config():config_path = os.path.join(os.path.dirname(__file__), 'config/config.yml')with open(config_path, 'r', encoding='utf-8') as f:configs = yaml.safe_load(f)base_config = configs.get('default', {})env_config = configs.get(CURRENT_ENV, {})print("当前配置环境:",CURRENT_ENV)print("当前配置参数:",{**base_config, **env_config})return {**base_config, **env_config}# 加载配置 config = load_config()# 初始化 Flask 应用 app = Flask(__name__) app.config.update(config)# 初始化数据库 db = SQLAlchemy(app)
mananger.py
from application import app from www import *if __name__ == '__main__':app.run(host="0.0.0.0",port=5000,debug=app.config.get('DEBUG', False))
config/config.yml
# 默认配置(所有环境都会继承这些基础配置) default:# 应用密钥,用于加密会话、CSRF保护等安全相关功能SECRET_KEY: "dev-secret-key"# 是否开启调试模式(默认关闭)# 注意:在生产环境中务必保持 DEBUG: false,避免泄露敏感信息DEBUG: false# 开发环境配置 development:# 数据库连接 URI,格式为:# mysql://用户名:密码@主机地址/数据库名SQLALCHEMY_DATABASE_URI: "mysql://root:yanpeng2580@localhost/rywork"# 开启调试模式,方便开发时查看错误信息DEBUG: true# 测试环境配置 testing:# 测试专用数据库,防止测试数据污染开发或生产数据SQLALCHEMY_DATABASE_URI: "mysql://root:yanpeng2580@localhost/test_db"# 同样开启调试模式,便于排查问题DEBUG: true# 生产环境配置 production:# 真实上线使用的数据库SQLALCHEMY_DATABASE_URI: "mysql://root:yanpeng2580@localhost/prod_db"# 关闭调试模式,提高安全性DEBUG: false
-
flask_debugtoolbar:
pip install flask_debugtoolbar
www.py
"""路由核心文件"""from application import appfrom controller.index import index_page# DEBUG工具引入from flask_debugtoolbar import DebugToolbarExtension# DEBUG工具注册实例化toolbar = DebugToolbarExtension(app)app.register_blueprint(index_page, url_prefix="/main")
mananger.py
from application import app from www import *if __name__ == '__main__':app.run(host="0.0.0.0",port=5000,# 开启 DEBUG debug=app.config.get('DEBUG', False))
WEB访问时,右侧显示
-
错误处理器
interceptors/errorHandler.py
""" 错误处理文件 """ from application import app@app.errorhandler(404) def error_404(error):return "<h1>404 错误处理页面</h1>"@app.errorhandler(500) def error_500(error):return "<h1>500 错误处理页面</h1>"
www.py
""" 路由核心文件 """ from application import app from controller.index import index_page # DEBUG工具引入 from flask_debugtoolbar import DebugToolbarExtension # 拦截器引入 from interceptors.Auth import * # 错误处理器 from interceptors.errorHandler import * # DEBUG工具注册实例化 toolbar = DebugToolbarExtension(app) app.register_blueprint(index_page, url_prefix="/main")
-
请求拦截器
interceptors/Auth.py
from application import app# 先拦截 @app.before_request def before_request():app.logger.info("拦截器!before_request")# return "ok"# 后拦截 @app.after_request def after_request(response):app.logger.info("拦截器!after_request")return response
www.py
""" 路由核心文件 """from application import app from controller.index import index_page # DEBUG工具引入 from flask_debugtoolbar import DebugToolbarExtension # 拦截器引入 from interceptors.Auth import *# DEBUG工具注册实例化 toolbar = DebugToolbarExtension(app) app.register_blueprint(index_page, url_prefix="/main")