You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask简易购物车开发技术问询:商品增删功能实现问题及购物车页面构建方法

Hey,我来帮你搞定Flask购物车的问题!先从核心的添加/删除、展示功能说起,再看看你的结账代码可以怎么优化~

一、构建Flask简易购物车核心功能

1. 先做好基础配置

首先要确保你的Flask app设置了SECRET_KEY,不然session(用来临时存购物车数据)没法正常工作:

from flask import Flask, render_template, request, session, redirect, url_for

app = Flask(__name__)
app.secret_key = 'your_secure_secret_key_here'  # 必须设置,建议用随机字符串

2. 实现「添加商品到购物车」功能

这里要考虑两种情况:商品已经在购物车(只增加数量)、商品不在购物车(新增条目):

@app.route('/add-to-cart/<int:product_id>', methods=['POST'])
def add_to_cart(product_id):
    # 模拟从数据库获取商品信息,实际项目替换为真实查询
    def get_product_from_db(prod_id):
        sample_products = {
            1: {'id': 1, 'name': 'Python入门指南', 'price': 59.9},
            2: {'id': 2, 'name': 'Flask实战手册', 'price': 79.9}
        }
        return sample_products.get(prod_id)
    
    product = get_product_from_db(product_id)
    if not product:
        return "商品不存在", 404
    
    # 初始化购物车session
    if 'cart' not in session:
        session['cart'] = []
    
    # 检查商品是否已在购物车
    existing_item = next((item for item in session['cart'] if item['id'] == product_id), None)
    if existing_item:
        existing_item['quantity'] += 1
    else:
        session['cart'].append({
            'id': product['id'],
            'name': product['name'],
            'price': product['price'],
            'quantity': 1
        })
    
    # 重点!修改session内的列表/字典后,必须手动标记修改,否则Flask不会保存更新
    session.modified = True
    return redirect(url_for('show_cart'))

3. 实现「从购物车删除商品」功能

支持两种删除逻辑:数量减1(数量为0时移除条目),或者直接移除商品:

@app.route('/remove-from-cart/<int:product_id>', methods=['POST'])
def remove_from_cart(product_id):
    if 'cart' not in session or not session['cart']:
        return redirect(url_for('show_cart'))
    
    cart = session['cart']
    target_item = next((item for item in cart if item['id'] == product_id), None)
    if target_item:
        if target_item['quantity'] > 1:
            target_item['quantity'] -= 1
        else:
            cart.remove(target_item)
        
        session.modified = True
    
    return redirect(url_for('show_cart'))

4. 购物车页面展示

写一个路由渲染购物车页面,把session里的购物车数据传给模板:

@app.route('/cart')
def show_cart():
    cart = session.get('cart', [])
    # 计算购物车总价
    total_amount = sum(item['price'] * item['quantity'] for item in cart)
    return render_template('cart.html', cart=cart, total=total_amount)

对应的极简模板cart.html示例:

<!DOCTYPE html>
<html>
<head>
    <title>我的购物车</title>
</head>
<body>
    <h1>购物车</h1>
    {% if cart %}
        <ul>
            {% for item in cart %}
                <li>
                    {{ item.name }} - ¥{{ item.price }} × {{ item.quantity }}
                    <!-- 减少数量按钮 -->
                    <form method="POST" action="{{ url_for('remove_from_cart', product_id=item.id) }}" style="display:inline;">
                        <button type="submit">-</button>
                    </form>
                    <!-- 增加数量按钮 -->
                    <form method="POST" action="{{ url_for('add_to_cart', product_id=item.id) }}" style="display:inline;">
                        <button type="submit">+</button>
                    </form>
                </li>
            {% endfor %}
        </ul>
        <p>总价: ¥{{ total }}</p>
        <!-- 结账表单 -->
        <form method="POST" action="{{ url_for('checkout') }}">
            <label>订单类型:
                <select name="order_type">
                    <option value="delivery">配送</option>
                    <option value="pickup">自提</option>
                </select>
            </label>
            <button type="submit">去结账</button>
        </form>
    {% else %}
        <p>购物车空空如也~快去挑选商品吧!</p>
    {% endif %}
    <a href="/">返回首页</a>
</body>
</html>
二、优化你的结账代码

你的结账逻辑已经走通,但可以加一些边界检查和异常处理,让代码更健壮:

@app.route('/checkout', methods=['POST'])
def checkout():
    user_id = session.get('user_id')
    # 检查用户是否登录
    if not user_id:
        return redirect(url_for('login'))  # 跳转到你的登录页面
    
    cart = session.get('cart', [])
    # 防止空购物车提交结账
    if not cart:
        return redirect(url_for('show_cart'))
    
    order_type = request.form.get('order_type')
    # 检查订单类型是否合法
    if not order_type or order_type not in ['delivery', 'pickup']:
        return "无效的订单类型", 400
    
    try:
        conn = get_db()
        # 用with上下文管理器,自动处理提交/回滚,避免忘记关闭连接
        with conn:
            c = conn.cursor()
            for item in cart:
                c.execute('''
                    INSERT INTO orders (user_id, product_id, quantity, order_type, status)
                    VALUES (?, ?, ?, ?, ?)
                ''', (user_id, item['id'], item['quantity'], order_type, "Pending"))
        # 清空购物车
        session.pop('cart', None)
        return redirect('/orders')
    except Exception as e:
        # 实际项目可以记录日志,这里简化返回错误提示
        return f"结账失败:{str(e)}", 500
三、常见踩坑点提示
  • 忘记设置session.modified = True:Flask的session是不可变对象,直接修改内部的列表/字典时,Flask不会自动检测到变化,必须手动标记才能保存更新。
  • 未做登录检查:如果允许未登录用户结账,会导致user_id为空,插入数据库时出错。
  • 数据库连接未正确关闭:用with语句管理连接是更安全的方式,避免资源泄漏。

内容的提问来源于stack exchange,提问作者ghosty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 10:37:27