前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【腾讯云 Cloud Studio 实战训练营】使用python-flask搭建自助售卖机实操

【腾讯云 Cloud Studio 实战训练营】使用python-flask搭建自助售卖机实操

原创
作者头像
用户8935260
发布2023-08-04 15:22:17
2870
发布2023-08-04 15:22:17
举报
文章被收录于专栏:python实操专栏

@toc

前言

各位小伙伴,欢迎来到Cloud Studio实战训练营!

Cloud Studio是一个基于浏览器的集成式开发环境(IDE),提供了一个无需安装的云端工作站。用户可以随时随地打开浏览器,在线进行编程。

使用Cloud Studio,开发者可以快速完成各种应用的开发、编译和部署工作。无论是个人项目还是团队协作,都能够提供便捷的开发环境和工具。同时,由于是基于云端的工作站,用户不需要担心本地环境配置和资源限制,可以随时访问和使用IDE进行开发。

今天我将带大家体验Cloud Studio的魅力,通过实际上手操作一个项目,来感受它的丝滑~

操作步骤

开发环境配置

登录(注册)Cloud Studio 账号:

打开Cloud Studio的官网,点击立即使用:

然后进行登录:

如果没有账号,就先进行注册,都是鹅厂的,想必相关账号大家都有,此处不再赘述。

进入 Cloud Studio 控制台:

登录成功之后就可以进入到Cloud Studio控制台了,界面如下:

这里内置了很多空间模板和应用,大家可以根据自己的需要进行选用。

在我本次演示中,咱们选择新建工作空间。

新建工作空间并配置参数:

空间名称:

空间描述:

工作类别:

代码来源:

选择仓库服务商:

开发环境:

版本:

规格配置:

参数看起来很多,但是实际上大部分都直接用默认值就可以。

大家把空间名称、空间描述(非必填)填写一下,再选择一下代码关联的仓库即可配置完毕(如果没有,选择空也可以)。

我这里填写的是这样的:

点击新建,稍等片刻,Cloud Studio就会为你创建出来相应的项目空间。

工作空间创建成功:

项目创建成功之后,就进入到了IDE编辑的界面,这个界面相信很多人都有一种莫名的亲切感吧,没错,就是和vscode界面一样,而且快捷键基本上都一样。

在这里你可以像在本地写代码一样完全沉浸其中!

至此,环境搭建完毕,现在正式开始搭建项目。

自动售卖机项目搭建

此项目仅为demo,供娱乐学习使用,本项目主要用python flask来搭建网站,用python连接mysql进行相应操作,实际操作步骤及相应代码文章都会涉及,需要的小伙伴不要错过哦~

项目文件目录结构如下:

|-- workspace

代码语言:txt
复制
|-- README.md
代码语言:txt
复制
|-- app.py
代码语言:txt
复制
|-- directoryList.md
代码语言:txt
复制
|-- static
代码语言:txt
复制
|   |-- axios.min.js
代码语言:txt
复制
|-- templates
代码语言:txt
复制
    |-- index.html

其中app.py为服务端文件,index.html为前端页面文件,axios.min.js为html中依赖的js文件(也可以直接用网址的方式来访问,网址为:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js但是我下载到了项目中,防止网络传输问题导致的访问不到)

项目主要文件就是这几个。

前端页面搭建

由于是用python flask框架搭建,所以需要在项目下面创建一个templates文件夹,将对应的模板html文件放入到其中,方便进行调用。

index.html的页面运行后的展示效果为:

主要功能就分为三块:

1.饮料列表展示区域和加入购物车按钮(需要后端接口:查询数据库所有饮料接口)
2.购物车展示区域(需要后端接口:结算操作)
3.结算结果展示区域

所以页面的源码也非常简单:

代码语言: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;
        }
    </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="{{ url_for('static', filename='axios.min.js') }}"></script>
    <script>
        const cart = {};

        // 发起 HTTP 请求获取商品数据
        axios.get("/goods")
          .then(response => {
            const goodsData = response.data;

            // 渲染商品列表
            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');
              const total_price = response.data.total_price;
              // 构造结果文本节点
              const resultText = document.createTextNode(`您本次总消费金额为:${total_price}元。`);
              // 清空结果容器并添加结果文本节点
              resultDiv.innerHTML = '';
              resultDiv.appendChild(resultText);
            })
            .catch(error => {
              console.error(error);
            });
        }
    </script>
</body>
</html>

服务端接口搭建

由于是用python flask框架来写服务端接口,所以,导入相应的包是必要的:

代码语言:python
代码运行次数:0
复制
from flask import Flask, jsonify, request, render_template

我们主要使用flask包中的相关模块,来进行html和flask的相关交互。

在对前端页面梳理的过程中,发现前端需要调用的接口有:

1.查询所有饮料接口

此处将查询出来的结果返回给前端页面即可。

2.购物车结算接口

根据前端返回的购物车中的商品,将价格进行累加,然后返回给前端最终结算金额即可。

后端代码:

代码语言:python
代码运行次数:0
复制
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)

# 饮料及其价格
goods = {
    "可乐": 3.0,
    "雪碧": 2.5,
    "橙汁": 4.0,
    "苹果汁": 3.5
}

@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')
    total_price = calculate_total_price(cart)
    # 处理其他相关逻辑...
    return jsonify({'message': '结算成功', 'total_price': total_price})

def calculate_total_price(cart):
    total_price = 0
    # print(cart)
    for drink, count in cart.items():
        if drink in goods:
            total_price += goods[drink] * count
    return total_price

if __name__ == '__main__':
    app.run()

此时运行app.py,会发现已经可以正常运行了,并且访问运行完给出的地址,也可以正常出来页面了,功能也都正常了。

至此,html和python flask接口已经成功调通了。

但是我们怎么会就此止步呢,细心的小伙伴已经发现了,饮料列表是写死的,这岂不是很不方便?而且在实际业务中也没有太大意义,那么接下来咱们就讲讲python连接数据库

连接数据库(mysql)

创建数据库表:

在mysql中创建一张drink表,来存放相应的饮料及价格。字段非常简单,就:name、price就可以了。

创建成功之后,给表中增加数据:

使用pymysql包来进行连接数据库:
代码语言:python
代码运行次数:0
复制
import pymysql

# MySQL数据库连接配置
db_config = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': 'Fatb6XNFXsY6MM',
    'database': 'drink',
    'port':3306
}

def query_data():
    goods={}
    # 建立MySQL数据库连接
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()
    query = f"SELECT * FROM drink"
    # 执行查询并获取结果
    cursor.execute(query)
    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()
    cursor.close()
    conn.close()
    # 将查询出来的结果转化为字典格式,方便兼容之前的代码
    for i in data:
        goods[i['name']]=i['price']
    return goods

注意:

1.数据库相关的配置,需要修改为自己的mysql连接时候的配置。(在Cloud Studio中,如果要连接mysql数据库,无法直接搭建mysql服务,需要连接到云服务器的数据库,云服务器中如何创建数据库,后面遇到的坑部分会详细介绍)

2.本案例中只简单尝试从数据库查询数据,其他的对数据库的增删改没有涉及,但是原理都一样,直接在query 语句上做相应的调整即可。

运行项目

直接运行app.py即可成功运行项目,运行效果图见下方:

然后点击 打开浏览器,即可在浏览器中访问该项目:

效果预览

我们修改数据库中的饮料以及价格,看看页面是否生效。

当前数据库中的数据为:

我们删掉苹果汁及其之后的所有饮料,增加一个石榴汁,定价为10.00元,然后将雪碧的价格也改为3.00。修改完的效果:

现在我们重新运行项目,看看页面是否生效了。

可以看到,页面已经生效了,并且计算的结算结果也没问题。

注意:此处修改了数据库之后,需要重新启动服务才可以让页面生效,因为服务端写的获取商品是在服务端脚本启动的时候就获取,之后就不再获取了,避免对数据库的高频次使用(这是我自己臆想的,哈哈)。

如果需要每次刷新页面都获取的话,可以将查询数据的逻辑放到主路由下面即可。

那些遇到的坑

数据库无法连接

我在自己本地运行代码的时候,由于本地安装了mysql,操作起来比较顺利,在使用Cloud Studio进行编写项目的时候,发现无法创建mysql,然后就懵逼了,思考了一下,那就只能连接云服务器的mysql了,还好我自己是有一台centos的云服务,装了宝塔,操作也比较傻瓜式。

操作记录如下:

1.在宝塔面板中,找到数据库菜单,然后点击添加数据库

2.添加数据库的时候,添加数据库名称,用户名,密码,选择访问权限,然后点击提交即可创建成功。

此处注意:访问权限这里,需要按照自己要求设置,否则可能会访问不到。

3.连接云服务器的数据库

用自己本地的数据库连接工具连接一下刚刚创建的云服务的mysql数据库,看是否可以正常连接。

填写的时候,主机需要填服务器的IP,端口,用户名和密码就按照你刚刚设置的填写即可,然后点击测试连接,如果成功,就说明连接上了。

注意:此处如果连接不上,请按照以下步骤排查:

1.端口在服务器内是否开放

2.端口在服务器防火墙是否放行

3.端口在服务器的安全策略是否放行

端口成功放行之后,应该是可以连接成功的。

然后将相应的配置修改到代码中即可。

总结与分析

Cloud Studio 整体使用非常顺畅丝滑,快捷的编译速度和流畅的操作,经常让你忘记使用的是本地编译器还是云IDE。

Cloud Studio的优势:
  • 跨平台和可访问性:CloudStudio 可以在任何有网络连接的设备上通过浏览器访问,包括桌面、笔记本电脑和移动设备。这样您可以轻松地从多个设备上访问和管理项目。
  • 无需安装和配置:使用 CloudStudio,您无需安装和配置任何开发工具和依赖项。一切都在云端完成,只需登录即可开始编写代码,这节省了时间和资源。
  • 协作和共享:CloudStudio 允许多人同时协作编辑和共享项目,使团队成员之间的沟通和合作更加简单和高效。您可以邀请他人参与到项目中,共同工作并实时交流。
  • 弹性和可扩展性:使用云基础设施,CloudStudio 可以根据您的需求进行弹性扩展。无论是处理大型项目还是需要更多计算资源,它都能够适应您的需求。
  • 自动保存和版本控制:CloudStudio 可以自动保存您的工作,并提供基本的版本控制功能。即使发生意外情况(例如断电或网络中断),您的代码也不会丢失,您可以轻松地恢复和追溯历史版本。

在具体编写代码方面表现也完全不输本地IDE:

  • 代码高亮:以不同颜色显示代码中的关键字,提高可读性。
  • 自动补全:根据输入的关键字,自动提示代码片段,减少编写代码的时间和错误。
  • Git集成:支持与Git版本控制系统的集成,方便代码管理和协作开发。
  • 终端:提供终端功能,可以在IDE中直接执行命令和脚本。
  • 实时调试:支持实时调试代码,帮助开发者找到并修复错误。
  • 插件扩展:可通过安装插件扩展IDE的功能,满足不同开发需求。
Cloud Studio的缺点:

1.缺乏本地文件系统访问:在线 IDE 无法直接访问您计算机的本地文件系统,无法方便地打开或保存位于计算机上的文件,而是需要通过上传和下载进行操作。

2.多文件传输麻烦:如果需要同时上传多个文件到在线 IDE 中,可能需要一个个文件逐个选择并上传,这可能会比本地 IDE 更加繁琐。

3.无法准确的获取到云IDE的IP,比如某些服务为了安全性考虑,需要将IP添加到白名单才可以访问,无法明确的获取到该云IDE的IP,从而导致无法添加到白名单。

希望官方可以进行相应的改进,将体验做的越来越好!

项目相关资源

至此,项目目标成功达成!撒花~

相关的项目资源链接附到这里,需要的小伙伴自取即可。

项目coding 地址

coding仓库地址:https://e.coding.net/dashixiong6668/auto_seller/auto_seller.git

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 操作步骤
    • 开发环境配置
      • 登录(注册)Cloud Studio 账号:
      • 进入 Cloud Studio 控制台:
      • 新建工作空间并配置参数:
      • 工作空间创建成功:
    • 自动售卖机项目搭建
      • 前端页面搭建
      • 服务端接口搭建
      • 连接数据库(mysql)
      • 运行项目
      • 效果预览
      • 那些遇到的坑
    • 总结与分析
      • 项目相关资源
        • 项目coding 地址
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档