1.前提准备
-
Python
版本# python 3.8.0 # 查看Python版本 python --version
-
安装第三方
Flask
pip 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-sqlalchemy
python
文件导入 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 routes
models.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)
再次启动项目:
页面能够正常访问