1.前提准备
-  Python版本# python 3.8.0 # 查看Python版本 python --version 
-  安装第三方 Flaskpip install flask # 如果安装失败,可以使用 -i,指定使用国内镜像源 # 清华镜像源:https://pypi.tuna.tsinghua.edu.cn/simple/
-  检查 Flask是否安装成功flask --version  
-  Flask官网 # 官网:https://flask.palletsprojects.com # 快速开始:https://flask.palletsprojects.com/en/3.0.x/quickstart/
2.一个简单的Flask程序
-  创建 Flask项目目录。mkdir FlaskMarket
-  创建 app文件。from flask import Flask  app = Flask(__name__)  @app.route("/") def hello_world():return "<p>Hello, World!</p>"
-  运行 Flask。flask --app market run # 设置环境变量,也能够直接运行flask $env:FLASK_APP="market.py" flask run 查看web页面  Debug 模式 # 运行flask项目时,在最后加--debug,以debug模式启动 $env:FLASK_APP="market.py" flask run --debug 以下是代码产生报错的截图  
-  新增一个路由。 # 路由传参username @app.route("/about/<username>") def about_page(username):return f"<h1>this is about {username} page</h1>"页面查询结果  
3.Template模板文件
可以在Flask项目的目录下创建 templates 目录存放所会用的 html 文件,具体如下:

在Python代码中,直接返回 html 文件即可,不需要携带目录。
@app.route("/")
def hello_world():return render_template("hello.html")页面访问如下

4.数据发送到template
Jinjia2 是一个仿照 Django 模板的 Python 模板语句,实现了后端与模板之间的交互。
-  一个简单的数据交互。 后端 python这样写:@app.route("/") def hello_world():return render_template("home.html", item_name="Phone")对应的前端 html文件需要使用jiajia2的语法接收变量,代码如下:<p>{{item_name}}</p>页面效果如下:  
-  列表数据交互。 后端 python这样写:@app.route("/") def hello_world():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]return render_template("home.html", items=items)对应的前端 html这样接收:<table class="table table-hover table-dark"><thead><tr><th scope="col">ID</th><th scope="col">Name</th><th scope="col">Barcode</th><th scope="col">Price</th></tr></thead><tbody>{% for item in items %}<tr><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.barcode}}</td><td>{{item.price}}</td></tr>{% endfor %}</tbody> </table>访问页面如下:  
5.Template 继承
开发的网站可能涉及多个页面,需要抽取公共的内容,其余的 html 页面继承这些公共内容即可。
-  引入 base.html文件。<!doctype html> <html lang="en"><head><!-- Required meta tags --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap CSS --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"><title>Base Title</title></head><body><!-- Navbar here --><nav class="navbar navbar-expand-md navbar-dark bg-dark"><a class="navbar-brand" href="#">EuanSu Coding Market</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="*navbarNav"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="#">Market</a></li></ul><ul class="navbar-nav"><li class="nav-item"><a class="nav-link" href="#">Login</a></li><li class="nav-item"><a class="nav-link" href="#">Register</a></li></ul></div> </nav><!-- Future Content here -->    <!-- Optional JavaScript --><!-- jQuery first, then Popper.js, then Bootstrap JS --><script src='https://kit.fontawesome.com/a076d05399.js'></script><script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script></body><style>body {background-color: #212121;color: white}</style> </html>
-  清空 home.html原文件,修改为如下内容:{% extends "base.html" %}
-  访问页面如下:  这里有一个问题就是页面标题显示为 Base Title,实际上每个页面的标题是不一样,这里可以通过block语句进行修改,代码如下:修改 base.html文件head下的title标签为如下内容:<head>...<title>{% block title%}{% endblock %}</title> </head>修改 home.html为如下内容:{% extends "base.html" %} {% block title%} Home Page {% endblock %}再次刷新页面, title的内容被替换。 
-  替换 html文件body下的内容:首先是修改 base.html中body的内容,修改如下:{% block content%} {% endblock %}修改 market.html为如下内容:{% extends "base.html" %} {% block title%} Market Page {% endblock %} {% block content%} <table class="table table-hover table-dark"><thead><tr><th scope="col">ID</th><th scope="col">Name</th><th scope="col">Barcode</th><th scope="col">Price</th></tr></thead><tbody>{% for item in items %}<tr><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.barcode}}</td><td>{{item.price}}</td><td><button class="btn btn-outline btn-info">More Info</button><button class="btn btn-outline btn-success">Purchase this Item</button></td></tr>{% endfor %}</tbody></table> {% endblock %}访问页面,能够正常对数据进行渲染。  
-  页面跳转 html文件的href进行跳转,这里需要使用jinjia2的语法,而不能直接使用路由。<a class="nav-link" href="{{ url_for('home_page') }}">Home <span class="sr-only">(current)</span></a> <a class="nav-link" href="{{ url_for('market_page') }}">Market</a>其中的 market_page是路由关联的函数,如下所示:@app.route("/") def home_page():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]return render_template("home.html", items=items)   @app.route("/market") def market_page():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]return render_template("market.html", items=items)再次点击页面的按钮,能够正常进行路由跳转。  
6.数据库模型
6.1 数据库模型的基本使用
安装 flask-sqlalchemy 第三方包。
pip install flask-sqlalchemypython 文件导入 flask-sqlalchemy 库。
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///market.sqlite'
db = SQLAlchemy(app)编写模型类。
class Item(db.Model):id = db.Column(db.Integer(), primary_key=True)name = db.Column(db.String(length=30),nullable=False, unique=True)price = db.Column(db.Integer(), nullable=True)barcode = db.Column(db.String(length=12), nullable=True, unique=True)description = db.Column(db.String(length=1024), nullable=True, unique=True)需要在 Flask 的 app 文件中,添加数据库初始化操作。
with app.app_context():db.create_all()使用可视化工具查看 SQLite 本地数据库文件,出现初始化的 Item 表。

6.2 SQLAlchemy 的基本使用
新增数据库记录
item1 =  Item(name="OPPO Find X6 Pro",price=5000,barcode='123456789',description='OPPO Find X6 Pro')
with app.app_context():db.session.add(item1)db.session.commit()
执行如上语句后,数据库中出现一条手机记录。

查询数据库记录
# 全量查询
result = Item.query.all()
print(result)
for item in result:print(item.name)
# 根据条件过滤
result = Item.query.filter_by(name='OPPO Find X6 Pro')
print(result)
print('=============')
for item in result:print(item.name)
修改数据库记录
result = Item.query.filter_by(name='OPPO Find X6 Pro')
if result:item = result[0]item.price = 5999db.session.commit()修改后,数据库中的记录发生了变化。

删除数据库记录
# 查询要删除的记录
record_to_delete = Item.query.filter_by(name="OnePlus 12").first()
# 如果记录存在,则删除
if record_to_delete:db.session.delete(record_to_delete)db.session.commit()这里的数据库查询放到代码中,如下:
@app.route("/market")
def market_page():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]items = Item.query.all()return render_template("market.html", items=items)页面就能够直接展示数据库中的记录

7.项目重构
# 这里将项目移动至mark目录下,主目录下仅留项目的启动文件 run.py D:\CODE\PYTHON\FLASKMARKET ├─instance ├─market │ ├─templates │ │ ├─css │ │ ├─js │ │ ├─base.html │ │ ├─home.html │ │ └─market.html │ ├─__init__.py │ ├─models.py │ ├─routes.py │ └─__pycache__ ├─run.py └─__pycache__
修改后的各文件一次如下所示:
__init__.py 模块初始化文件:
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///market.sqlite'
db = SQLAlchemy(app)
from market import routesmodels.py 模型文件:
from market import db
class Item(db.Model):id = db.Column(db.Integer(), primary_key=True)name = db.Column(db.String(length=30),nullable=False, unique=True)price = db.Column(db.Integer(), nullable=True)barcode = db.Column(db.String(length=12), nullable=True, unique=True)description = db.Column(db.String(length=1024), nullable=True, unique=True)routes.py 路由文件:
from market import app
from flask import render_template
from market.models import Item
@app.route("/")
@app.route("/home")
def home_page():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]return render_template("home.html", items=items)
@app.route("/market")
def market_page():items = [{"id": 1, "name": "Phone", "barcode": 123456789, "price": 500},{"id": 2, "name": "Laptop", "barcode": 123654789, "price": 500},{"id": 3, "name": "keybord", "barcode": 123456987, "price": 150},]items = Item.query.all()return render_template("market.html", items=items)再次启动项目:

页面能够正常访问
