写点什么

用 Python 与 KWDB 打造智能自动售卖机:从搭建到实践

作者:KaiwuDB
  • 2025-07-02
    重庆
  • 本文字数:6249 字

    阅读完需:约 21 分钟

用 Python 与 KWDB 打造智能自动售卖机:从搭建到实践

作者:大师兄 6668


原文链接:https://blog.csdn.net/qq_41308872/article/details/147178215


在开发技术不断革新的当下,将 Python 的灵活编程能力与 KWDB 强大的数据管理性能相结合,能创造出功能丰富且高效的应用程序。本文将带领大家利用这两者打造一个自动售卖机系统,从环境搭建、功能实现到最终优化,逐步揭开项目的神秘面纱。


在前三篇博文中,我们已经成功在 Centos 云服务中通过 Docker 安装了 KWDB,在 CentOS 云服务中通过 Docker 安装 KWDB 数据库并且掌握了在云服务器上直接连接 KWDB 进行增删改查的操作方法。【云服务器连接已部署 KWDB 并进行增删改查操作】完整指南而且深入探索如何通过 Python 语言连接 KWDB,【通过 Python 连接 KWDB 数据库】的完整步骤与示例接下来,我们利用这些知识,直接做一个简单的项目——《智能自动售卖机》我们借助 Python 丰富的生态库,进一步来拓展 KWDB 在数据处理和应用开发方面的能力。


开发环境配置


安装 Python


Python 作为项目的核心开发语言,可从 Python 官方网站下载安装包进行安装。建议安装最新稳定版本,以获取更好的性能和功能支持。安装过程中,记得勾选“Add Python to PATH”选项,方便后续在命令行中直接调用 Python。


安装 KWDB


若 KWDB 尚未安装,可通过 Docker 进行快速部署。以 Centos 云服务为例,先确保已安装 Docker,接着拉取 KWDB 镜像:docker pull kwdb/kwdb:latest。之后创建 docker-compose.yml 文件,配置容器参数:


version: '3.3'services:  kaiwudb-container:    image: "kwdb/kwdb:latest"    container_name: kaiwudb-experience    hostname: kaiwudb-experience    ports:      - 8080:8080      - 26257:26257    ulimits:      memlock: -1    volumes:      - /dev:/dev    networks:       - default    restart: on-failure    ipc: shareable    privileged: true    environment:      - LD_LIBRARY_PATH=/kaiwudb/lib    tty: true    working_dir: /kaiwudb/bin    command:       - /bin/bash      - -c      - |        /kaiwudb/bin/kwbase start-single-node --insecure --listen-addr=0.0.0.0:26257 --advertise-addr=127.0.0.1:26257 --http-addr=0.0.0.0:8080 --store=/kaiwudb/deploy/kaiwudb
复制代码


保存文件后,在所在目录执行 docker-compose up -d 启动 KWDB 服务。


安装相关 Python 库


项目中需使用 psycopg 库连接 KWDB,通过 pip 进行安装:pip install "psycopg[binary]"。若涉及 Web 开发,还可安装 Flask 框架:pip install flask,方便构建售卖机的前端交互界面。


自动售卖机项目搭建


数据库设计


在 KWDB 中创建数据库和表存储饮料信息。可使用 kwbase CLI 工具连接 KWDB,创建名为 vending_machine 的数据库:CREATE DATABASE vending_machine;。



接着在数据库内创建 drinks 表,存储饮料名称、价格、库存等信息:


CREATE TABLE vending_machine.drinks (    id INT AUTO_INCREMENT PRIMARY KEY,    name VARCHAR(255) NOT NULL,    price DECIMAL(10, 2) NOT NULL,    stock INT NOT NULL);
复制代码



插入一些初始饮料数据:


INSERT INTO vending_machine.drinks (name, price, stock) VALUES ('可乐', 3.00, 10),('雪碧', 2.50, 10),('橙汁', 4.00, 10);
复制代码



服务端接口搭建


借助 Flask 框架开发服务端接口,实现饮料查询、购物车结算等功能。创建 app.py 文件,编写如下代码:


from flask import Flask, jsonify, request, render_templateimport psycopg
app = Flask(__name__)
# 连接KWDB数据库def connect_kwdb(): url = "postgresql://root@你的云服务器IP:26257/defaultdb" try: conn = psycopg.connect(url) return conn except psycopg.Error as e: print(f"连接KWDB失败: {e}") return None
def query_data(): goods={} conn = connect_kwdb() if not conn: return jsonify({"error": "无法连接数据库"}), 500 cursor = conn.cursor() try: cursor.execute("SELECT name, price, stock FROM vending_machine.drinks;") result = cursor.fetchall() data=[] if len(result) > 0: columns = [desc[0] for desc in cursor.description] table_data = [{columns[i]: row[i] for i in range(len(columns))} for row in result] data.extend(table_data)
# 提交事务并关闭连接 conn.commit()
except psycopg.Error as e: return jsonify({"error": f"查询饮料失败: {e}"}), 500 finally: cursor.close() conn.close() for i in data: goods[i['name']]=i['price'] return goods
# 将数据库取出来的数据赋值给goodsgoods=query_data()

@app.route('/')def index(): return render_template('index.html',goods=goods)
@app.route('/goods', methods=['GET'])def get_goods(): return jsonify(goods)



# 购物车结算接口@app.route('/checkout', methods=['POST'])def checkout(): cart = request.json.get('cart') if not cart: return jsonify({"error": "购物车数据为空"}), 400 conn = connect_kwdb() if not conn: return jsonify({"error": "无法连接数据库"}), 500 cursor = conn.cursor() total_price = 0 for drink, count in cart.items(): try: cursor.execute("SELECT price, stock FROM vending_machine.drinks WHERE name = %s", (drink,)) drink_info = cursor.fetchone() if drink_info: price, stock = drink_info if stock < count: return jsonify({"error": f"{drink}库存不足"}), 400 total_price += price * count except psycopg.Error as e: return jsonify({"error": f"结算失败: {e}"}), 500 try: for drink, count in cart.items(): cursor.execute("UPDATE vending_machine.drinks SET stock = stock - %s WHERE name = %s", (count, drink)) conn.commit() return jsonify({'message': '结算成功', 'total_price': total_price}) except psycopg.Error as e: conn.rollback() return jsonify({"error": f"更新库存失败: {e}"}), 500 finally: cursor.close() conn.close()


if __name__ == '__main__': app.run()
复制代码


前端页面搭建


使用 HTML、CSS 和 JavaScript 构建前端页面,展示饮料列表、购物车及结算结果。在项目目录下创建 templates 文件夹,放入 index.html 文件:


<!DOCTYPE html><html><head>    <title>饮料自动售货机</title>    <style>        body {            font-family: Arial, sans-serif;            margin: 0;            padding: 20px;            background-color: #f2f2f2;        }      .container {            max-width: 800px;            margin: 0 auto;            background-color: #fff;            padding: 30px;            border-radius: 5px;            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);        }        h2 {            color: #333;            margin-top: 0;        }      .button {            background-color: #4CAF50;            color: white;            padding: 10px 20px;            border: none;            cursor: pointer;            font-size: 16px;            border-radius: 3px;        }      .button:hover {            opacity: 0.8;        }      .goods-list,.cart,.checkout-result {            margin-bottom: 20px;        }      .goods-list-item {            display: flex;            align-items: center;            justify-content: space-between;            padding: 10px;            border-bottom: 1px solid #ccc;        }      .goods-list-item:last-child {            border-bottom: none;        }      .cart-item {            display: flex;            align-items: center;            justify-content: space-between;            padding: 10px;            border-bottom: 1px solid #ccc;        }      .cart-item:last-child {            border-bottom: none;        }        .success-message {            color: #28a745;            padding: 10px;            border: 1px solid #28a745;            border-radius: 4px;            margin: 10px 0;        }
.error-message { color: #dc3545; padding: 10px; border: 1px solid #dc3545; border-radius: 4px; margin: 10px 0; } </style></head><body> <div class="container"> <h2>饮料列表</h2> <div class="goods-list" id="goods-list"></div>
<hr>
<h2>购物车</h2> <div class="cart" id="cart"></div>
<button class="button" onclick="checkout()">结算</button>
<hr>
<h2>结算结果</h2> <div class="checkout-result" id="checkout-result"></div> </div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> const cart = {};
// 发起HTTP请求获取商品数据 axios.get("/goods") .then(response => { const goodsData = response.data; console.log('========',goodsData)
// 渲染商品列表 const goodsListDiv = document.getElementById('goods-list'); for (const drink in goodsData) { const price = goodsData[drink];
const drinkDiv = document.createElement('div'); const drinkText = document.createTextNode(drink + ": " + price + " 元"); drinkDiv.appendChild(drinkText);
const addButton = document.createElement('button'); addButton.textContent = "加入购物车"; addButton.addEventListener('click', function() { addToCart(drink); });
drinkDiv.appendChild(addButton); goodsListDiv.appendChild(drinkDiv); } }) .catch(error => { console.error(error); });
// 添加到购物车的逻辑 function addToCart(drink) { if (cart.hasOwnProperty(drink)) { cart[drink]++; } else { cart[drink] = 1; }
renderCart(); }
// 渲染购物车 function renderCart() { const cartDiv = document.getElementById('cart'); cartDiv.innerHTML = '';
for (const drink in cart) { const quantity = cart[drink];
const itemDiv = document.createElement('div'); const itemText = document.createTextNode(drink + ": " + quantity + "杯"); itemDiv.appendChild(itemText);
cartDiv.appendChild(itemDiv); } }
// 结算函数 function checkout() { axios.post('/checkout', {cart: cart}) .then(response => { const resultDiv = document.getElementById('checkout-result'); // 清空之前的样式和内容 resultDiv.innerHTML = ''; resultDiv.className = ''; // 处理成功响应 if (response.data.message === '结算成功') { const total_price = response.data.total_price; resultDiv.className = 'success-message'; resultDiv.innerHTML = `✅ ${response.data.message}<br>总消费金额:${total_price}元`; } // 处理其他可能的成功状态 else { resultDiv.className = 'error-message'; resultDiv.textContent = response.data.error || '未知响应'; } }) .catch(error => { const resultDiv = document.getElementById('checkout-result'); // 清空之前的样式和内容 resultDiv.innerHTML = ''; resultDiv.className = 'error-message'; if (error.response) { // 处理HTTP状态码为4xx/5xx的响应 const serverError = error.response.data.error; if (serverError) { resultDiv.innerHTML = `❌ 错误:${serverError}`; } else { resultDiv.textContent = `请求错误:${error.response.status}`; } } else if (error.request) { // 请求已发送但没有收到响应 resultDiv.textContent = "网络错误,请检查连接状态"; } else { // 其他错误 resultDiv.textContent = `请求失败:${error.message}`; } }); }
</script></body></html>
复制代码


运行项目与效果预览


在项目目录下,执行 python app.py 启动服务。若一切正常,可在浏览器中访问http://127.0.0.1:5000查看自动售卖机页面。用户能看到饮料列表及库存信息,点击“加入购物车”按钮添加饮料,结算时系统会检查库存并计算总价,同时更新数据库中的库存数据。


初始页面



正常结算页面



异常页面



总结与展望


通过 Python 与 KWDB 的协同工作,成功打造了一个功能完备的自动售卖机系统。KWDB 强大的数据存储和管理能力,确保饮料数据的高效处理;Python 凭借丰富的库和简洁的语法,让开发过程变得轻松便捷。后续可进一步优化系统,如添加用户登录注册功能、完善库存预警机制等,不断提升用户体验。希望本文能为大家在相关开发领域提供有益参考,激发更多创新实践。


发布于: 2025-07-02阅读数: 2
用户头像

KaiwuDB

关注

还未添加个人签名 2021-04-29 加入

KaiwuDB 是浪潮集团控股的数据库企业,公司汇聚了全球顶尖的数据库人才,以多模数据库为核心产品,面向工业物联网、数字能源、交通车联网、智慧产业等各大行业领域,提供领先创新的数据服务软件。

评论

发布
暂无评论
用 Python 与 KWDB 打造智能自动售卖机:从搭建到实践_KaiwuDB_InfoQ写作社区