介绍
示如何使用 Python、Flask、MySQL 编写一个简单的购物车?
这个购物车非常简单,它没有结帐选项,付款选项。
这是关于在在线购物门户中显示产品,将商品添加到购物车,
从购物车中删除商品并一次性从购物车中删除所有商品或清空购物车。
先决条件
Python 3.7.4 – 3.9.1, MySQL 8.0.17 – 8.0.22, Flask 1.1.1 – 1.1.2
目录
创建一个项目根目录,您将在该目录下放置项目所需的所有文件。
假设我要创建一个项目根目录python_flask_mysql_shopping_cart。
MySQL 表
在MySQL服务器中的数据库roytuts下创建一个产品表,结构如下:
CREATE TABLE `product` (
`id` int unsigned COLLATE utf8mb4_unicode_ci NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`image` text COLLATE utf8mb4_unicode_ci NOT NULL,
`price` double COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
在产品表中写入一些临时数据(随便写的,不要对号入座)。
INSERT INTO `product` (`id`, `name`, `code`, `image`, `price`) VALUES
(1, '华为电脑', '华为book01', 'product-images/huawei.jpg', 12000.00),
(2, '华为手机', 'MATE6000', 'product-images/MATE6000.jpg', 6000.00),
(3, '华为服务器', 'mi6000', 'product-images/X6000.jpg', 15000.00),
(4, '华为路由器', 'FBE13 Pro', 'product-images/BE3Pro.jpg', 299.00),
(5, '华为汽车', 'car01', 'product-images/car.jpg', 550000.00),
(6, '小星星汽车', 'MB06', 'product-images/mb06.jpg', 300000.00),
(7, '小星星手机', 'pp01', 'product-images/pp01.jpg', 3000.00),
(8, '小猫咪猫抓板', 'cat01', 'product-images/cat01.jpg', 400.00);
配置 Flask
创建 app.py,导入flask 模块。
此文件在项目根目录下创建。
请注意如何创建 flask 实例。我已经配置了一个密钥,这是应用程序会话所必需的。
from flask import Flask
app = Flask(__name__)
app.secret_key = "secret key"
数据库配置
在项目根目录下创建db_config.py ,
以设置用于连接到数据库的 MySQL 数据库配置。
使用 flask 模块配置数据库连接,导入应用程序模块并使用 flask 模块设置 MySQL 配置。
from app import app
from flaskext.mysql import MySQL
mysql = MySQL()
# MySQL 数据库的配置,账号、密码、数据库名、地址或IP
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'roytuts'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
配置 URL
创建 main.py 脚本,该脚本将定义所有 URI 或操作路径,以执行用于购物车的某些操作或从数据库中获取所有产品。
它将连接到MySQL数据库服务器并查询数据库以从数据库表中读取所有产品。
首先将所需的模块导入脚本中。然后,我定义了显示视图的路由/
,用户将在其中看到所有产品。
接下来,需要验证用户输入数据并将这些输入数据保存到购物车中。
所以定义了另一个路由/add
。根据产品代码从MySQL数据库中获取数据,并针对唯一的产品密钥放入会话中。
使用http方法GET显示视图,使用POST方法将数据发送到服务器端。默认情况下,如果未指定 http 方法,则 http 方法为 GET。
使用flask中的render_template函数来显示视图。
当购物车中没有产品或商品时,将不会在主页或产品页面上看到购物车中的任何商品或产品。
如果从每个产品上显示的“添加到购物车”链接将产品添加到购物车,则您将看到产品被添加并显示到购物车中。
我定义路由/empty
以清除购物车中的所有商品。
接下来,我定义用户从购物车中逐个删除产品的路由/delete/<string:code>
。(<string:code>
为参数)
import pymysql
from app import app
from db_config import mysql
from flask import flash, session, render_template, request, redirect, url_for
#从工具导入generate_password_hash
from werkzeug.security import generate_password_hash, check_password_hash
@app.route('/add', methods=['POST'])
def add_product_to_cart():
cursor = None
try:
_quantity = int(request.form['quantity'])
_code = request.form['code']
# validate the received values
if _quantity and _code and request.method == 'POST':
conn = mysql.connect()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT * FROM product WHERE code=%s", _code)
row = cursor.fetchone()
itemArray = { row['code'] : {'name' : row['name'], 'code' : row['code'], 'quantity' : _quantity, 'price' : row['price'], 'image' : row['image'], 'total_price': _quantity * row['price']}}
all_total_price = 0
all_total_quantity = 0
session.modified = True
if 'cart_item' in session:
if row['code'] in session['cart_item']:
for key, value in session['cart_item'].items():
if row['code'] == key:
#session.modified = True
#if session['cart_item'][key]['quantity'] is not None:
# session['cart_item'][key]['quantity'] = 0
old_quantity = session['cart_item'][key]['quantity']
total_quantity = old_quantity + _quantity
session['cart_item'][key]['quantity'] = total_quantity
session['cart_item'][key]['total_price'] = total_quantity * row['price']
else:
session['cart_item'] = array_merge(session['cart_item'], itemArray)
for key, value in session['cart_item'].items():
individual_quantity = int(session['cart_item'][key]['quantity'])
individual_price = float(session['cart_item'][key]['total_price'])
all_total_quantity = all_total_quantity + individual_quantity
all_total_price = all_total_price + individual_price
else:
session['cart_item'] = itemArray
all_total_quantity = all_total_quantity + _quantity
all_total_price = all_total_price + _quantity * row['price']
session['all_total_quantity'] = all_total_quantity
session['all_total_price'] = all_total_price
return redirect(url_for('.products'))
else:
return '将商品添加到购物车时出错'
except Exception as e:
print(e)
finally:
cursor.close()
conn.close()
@app.route('/')
def products():
try:
conn = mysql.connect()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT * FROM product")
rows = cursor.fetchall()
return render_template('products.html', products=rows)
except Exception as e:
print(e)
finally:
cursor.close()
conn.close()
@app.route('/empty')
def empty_cart():
try:
session.clear()
return redirect(url_for('.products'))
except Exception as e:
print(e)
@app.route('/delete/<string:code>')
def delete_product(code):
try:
all_total_price = 0
all_total_quantity = 0
session.modified = True
for item in session['cart_item'].items():
if item[0] == code:
session['cart_item'].pop(item[0], None)
if 'cart_item' in session:
for key, value in session['cart_item'].items():
individual_quantity = int(session['cart_item'][key]['quantity'])
individual_price = float(session['cart_item'][key]['total_price'])
all_total_quantity = all_total_quantity + individual_quantity
all_total_price = all_total_price + individual_price
break
if all_total_quantity == 0:
session.clear()
else:
session['all_total_quantity'] = all_total_quantity
session['all_total_price'] = all_total_price
#return redirect('/')
return redirect(url_for('.products'))
except Exception as e:
print(e)
def array_merge( first_array , second_array ):
if isinstance( first_array , list ) and isinstance( second_array , list ):
return first_array + second_array
elif isinstance( first_array , dict ) and isinstance( second_array , dict ):
return dict( list( first_array.items() ) + list( second_array.items() ) )
elif isinstance( first_array , set ) and isinstance( second_array , set ):
return first_array.union( second_array )
return False
if __name__ == "__main__":
app.run()
模板文件
创建products.html文件并将其放在 /templates 目录下。
请注意,如何使用 flask EL 表达式来使用变量将数据显示到 HTML 文件中。
添加了一个链接,用户可以使用该链接清空购物车,并且仅当至少将一种产品添加到购物车时才会显示此链接。
检查是否有任何成功或错误消息并显示它们。
对于会话所需要的密钥,就是在脚本app.py中配置密钥的原因 。
最后,我将产品显示到HTML页面中。
<!DOCTYPE html>
<html>
<head>
<title>Python Flask 购物车示例</title>
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
<div id="shopping-cart">
<div class="txt-heading">购 物 车 测 试</div>
{% if 'cart_item' in session %}
<a id="btnEmpty" href="{{ url_for('.empty_cart') }}">清空购物车</a>
<table class="tbl-cart" cellpadding="10" cellspacing="1">
<tbody>
<tr>
<th style="text-align:left;">名称</th>
<th style="text-align:left;">编码</th>
<th style="text-align:right;" width="5%">数量</th>
<th style="text-align:right;" width="10%">单价</th>
<th style="text-align:right;" width="10%">合计</th>
<th style="text-align:center;" width="5%">移除</th>
</tr>
{% for key, val in session['cart_item'].items() %}
{% set quantity = session['cart_item'][key]['quantity'] %}
{% set price = session['cart_item'][key]['price'] %}
{% set item_price = session['cart_item'][key]['total_price'] %}
<tr>
<td><img src="/static/images/{{ session['cart_item'][key]['image'] }}" class="cart-item-image" />{{ session['cart_item'][key]['name'] }}</td>
<td>{{ session['cart_item'][key]['code'] }}</td>
<td style="text-align:right;">{{ quantity }}</td>
<td style="text-align:right;">₹ {{ price }}</td>
<td style="text-align:right;">₹ {{ item_price }}</td>
<td style="text-align:center;">
<a href="{{ url_for('.delete_product', code=session['cart_item'][key]['code']) }}" class="btnRemoveAction">
<img src="/static/images/icon-delete.png" alt="Remove Item" />
</a>
</td>
</tr>
{% endfor %}
<tr>
<td colspan="2" align="right">总计:</td>
<td align="right">{{ session['all_total_quantity'] }}</td>
<td align="right" colspan="2"><strong>₹ {{ session['all_total_price'] }}</strong></td>
<td></td>
</tr>
</tbody>
</table>
{% else: %}
<div class="no-records">您的购物车尚未选择商品</div>
{% endif %}
</div>
<div id="product-grid">
<div class="txt-heading">商品列表</div>
{% for product in products %}
<div class="product-item">
<form method="post" action="/add">
<div class="product-image"><img src="/static/images/{{ product.image }}"></div>
<div class="product-tile-footer">
<div class="product-title">{{ product.name }}</div>
<div class="product-price">₹ {{ product.price }}</div>
<div class="cart-action">
<input type="hidden" name="code" value="{{ product.code }}"/>
<input type="text" class="product-quantity" name="quantity" value="1" size="2" />
<input type="submit" value="Add to Cart" class="btnAddAction" />
</div>
</div>
</form>
</div>
{% endfor %}
</div>
</body>
</html>
测试程序
现在从命令行执行python main.py
main.py
将在默认端口5000
上启动。
如果要更改端口,则可以将行app.run()
更改为app.run(port=50001)
,其中app.run()
是新端口。
在浏览器中点击 URL http://localhost:5000/
这就是如何使用 Python Flask 和 MySQL 构建简单的购物车的全部内容。