用 Python + MySQL

从零搭建电商平台

—— 零基础入门完整教程 ——

本文适合:初学者  |  涵盖:数据库设计 · Python连接 · CRUD · 用户系统

第一章  项目介绍与环境准备

1.1 项目概述

本教程将带你从零开始,使用 Python 和 MySQL 联合构建一个简单的电商平台后端系统。电商平台是日常生活中最常见的应用场景之一,涵盖了用户管理、商品管理、购物车和订单处理等核心功能,是学习数据库与后端编程结合的绝佳例子。

通过本教程,你将学会:

如何设计关系型数据库(MySQL)

如何用 Python 连接并操作 MySQL

如何实现用户注册和登录功能

如何对商品和订单进行增删改查(CRUD)操作

� 提示  本教程面向完全零基础的读者。每一步都有详细说明,请放心跟随学习!

1.2 技术栈说明

技术

用途说明

Python 3.x

主要编程语言,负责业务逻辑处理

MySQL 8.x

关系型数据库,存储所有数据

mysql-connector-python

Python 连接 MySQL 的官方驱动库

hashlib

Python 内置库,用于密码加密(MD5/SHA256)

1.3 环境安装

安装 Python

访问 https://www.python.org/downloads/ 下载 Python 3.x 版本,安装时勾选 Add Python to PATH 选项。

安装完成后,打开命令行验证:

# 验证 Python 安装

python --version

# 应该显示类似:Python 3.11.0

安装 MySQL

访问 https://dev.mysql.com/downloads/mysql/ 下载并安装 MySQL 8.x。安装时请牢记设置的 root 密码。

安装 Python MySQL 驱动

打开命令行(终端),执行以下命令安装连接库:

pip install mysql-connector-python

� 提示  如果安装缓慢,可以使用国内镜像:pip install mysql-connector-python -i https://pypi.tuna.tsinghua.edu.cn/simple

第二章  数据库设计与建表

2.1 数据库设计思路

一个电商平台至少需要以下四张核心表:

表名

中文名

存储内容

users

用户表

用户基本信息、密码

products

商品表

商品名称、价格、库存

orders

订单表

谁购买了什么、金额

order_items

订单明细表

每个订单包含的具体商品

这四张表之间有明确的关联关系:一个用户可以有多个订单,一个订单可以包含多件商品,这就是关系型数据库的核心思想。

2.2 创建数据库

打开 MySQL 命令行(或 MySQL Workbench),执行以下 SQL 语句创建数据库:

-- 创建电商数据库

CREATE DATABASE IF NOT EXISTS ecommerce

    CHARACTER SET utf8mb4

    COLLATE utf8mb4_unicode_ci;

-- 切换到该数据库

USE ecommerce;

� 提示  utf8mb4 是 MySQL 中最完整的 UTF-8 字符集,支持中文、Emoji 等所有字符,推荐使用。

2.3 创建用户表(users)

CREATE TABLE users (

    id          INT AUTO_INCREMENT PRIMARY KEY,   -- 主键,自增

    username    VARCHAR(50)  NOT NULL UNIQUE,     -- 用户名,不可重复

    password    VARCHAR(64)  NOT NULL,            -- 加密后的密码

    email       VARCHAR(100) NOT NULL UNIQUE,     -- 邮箱,不可重复

    created_at  DATETIME DEFAULT CURRENT_TIMESTAMP -- 注册时间

);

字段说明:

id:主键(PRIMARY KEY),每个用户唯一标识,AUTO_INCREMENT 代表自动递增

username:用户名,UNIQUE 约束确保不会有重复用户名

password:密码存储的是加密后的字符串,绝不存明文

created_at:用 DEFAULT CURRENT_TIMESTAMP 让 MySQL 自动填写注册时间

2.4 创建商品表(products)

CREATE TABLE products (

    id          INT AUTO_INCREMENT PRIMARY KEY,

    name        VARCHAR(200) NOT NULL,      -- 商品名称

    description TEXT,                       -- 商品描述

    price       DECIMAL(10, 2) NOT NULL,    -- 价格(精确到分)

    stock       INT DEFAULT 0,              -- 库存数量

    created_at  DATETIME DEFAULT CURRENT_TIMESTAMP

);

� 提示  价格使用 DECIMAL(10, 2) 而不是 FLOAT,是因为浮点数在计算机中有精度误差,涉及金钱必须用 DECIMAL。

2.5 创建订单表(orders)

CREATE TABLE orders (

    id           INT AUTO_INCREMENT PRIMARY KEY,

    user_id      INT NOT NULL,                       -- 关联用户

    total_amount DECIMAL(10, 2) NOT NULL,            -- 订单总金额

    status       ENUM('pending','paid','cancelled')  -- 订单状态

                 DEFAULT 'pending',

    created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,

    FOREIGN KEY (user_id) REFERENCES users(id)       -- 外键约束

);

这里引入了两个重要概念:

ENUM:枚举类型,限定字段只能是几个固定值之一,防止输入错误数据

FOREIGN KEY(外键):确保 user_id 必须在 users 表中存在,保证数据完整性

2.6 创建订单明细表(order_items)

CREATE TABLE order_items (

    id           INT AUTO_INCREMENT PRIMARY KEY,

    order_id     INT NOT NULL,

    product_id   INT NOT NULL,

    quantity     INT NOT NULL,              -- 购买数量

    unit_price   DECIMAL(10, 2) NOT NULL,   -- 下单时的单价

    FOREIGN KEY (order_id)   REFERENCES orders(id),

    FOREIGN KEY (product_id) REFERENCES products(id)

);

� 提示  为什么要单独存 unit_price?因为商品价格可能随时变动,订单明细需要记录下单那一刻的价格,这是电商系统的重要设计原则。

第三章  Python 连接 MySQL

3.1 建立数据库连接

创建一个名为 db_config.py 的文件,专门管理数据库连接:

# db_config.py

import mysql.connector

def get_connection():

    """获取数据库连接"""

    connection = mysql.connector.connect(

        host     = 'localhost',   # 数据库服务器地址

        user     = 'root',        # 数据库用户名

        password = '你的密码',    # 数据库密码

        database = 'ecommerce',   # 使用的数据库名

        charset  = 'utf8mb4'

    )

    return connection

# 测试连接

if __name__ == '__main__':

    conn = get_connection()

    print('数据库连接成功!')

    conn.close()

运行测试:

python db_config.py

# 输出:数据库连接成功!

� 提示  将数据库配置单独放在一个文件中是良好的编程习惯,方便后续修改,也避免密码散落在代码各处。

3.2 连接的核心概念

Python 操作 MySQL 时,需要理解两个核心对象:

对象

名称

作用

connection

连接对象

代表与数据库的连接通道,负责提交/回滚

cursor

游标对象

用于执行 SQL 语句和获取结果

conn   = get_connection()       # 建立连接

cursor = conn.cursor()          # 创建游标

cursor.execute('SELECT ...')    # 执行 SQL

result = cursor.fetchall()      # 获取所有结果

conn.commit()                   # 提交事务(增删改需要)

cursor.close()                  # 关闭游标

conn.close()                    # 关闭连接

第四章  用户注册与登录

4.1 密码加密原理

存储密码时,注意绝对不能存明文!大家想象一下,如果数据库被黑客攻击,所有用户的密码都会泄露。正确的做法是使用哈希算法对密码进行单向加密。

本教程使用 SHA-256 算法:

SHA-256 是单向的:给定密码可以生成哈希值,但无法从哈希值反推密码

相同的密码总是产生相同的哈希值,因此验证时只需对比哈希值即可

# 密码加密示例

import hashlib

def hash_password(password: str) -> str:

    """对密码进行 SHA-256 加密"""

    return hashlib.sha256(password.encode('utf-8')).hexdigest()

# 测试

print(hash_password('mypassword123'))

# 输出:加密后的64位十六进制字符串

4.2 用户注册功能

创建 user_service.py 文件,实现注册功能:

# user_service.py

import hashlib

from db_config import get_connection

def hash_password(password: str) -> str:

    return hashlib.sha256(password.encode('utf-8')).hexdigest()

def register_user(username: str, password: str, email: str):

    """用户注册"""

    conn   = get_connection()

    cursor = conn.cursor()

    try:

        sql = """

            INSERT INTO users (username, password, email)

            VALUES (%s, %s, %s)

        """

        hashed_pwd = hash_password(password)

        cursor.execute(sql, (username, hashed_pwd, email))

        conn.commit()

        print(f'用户 {username} 注册成功!')

        return True

    except Exception as e:

        conn.rollback()  # 出错则回滚

        print(f'注册失败:{e}')

        return False

    finally:

        cursor.close()

        conn.close()

� 提示  注意 SQL 语句中使用 %s 占位符而非直接拼接字符串,这是防止 SQL 注入攻击的关键!永远不要写 f"... WHERE name='{user_input}'" 这样的代码。

4.3 用户登录功能

def login_user(username: str, password: str):

    """用户登录,验证成功返回用户信息,否则返回 None"""

    conn   = get_connection()

    cursor = conn.cursor(dictionary=True)  # 返回字典格式

    try:

        sql = 'SELECT * FROM users WHERE username = %s'

        cursor.execute(sql, (username,))

        user = cursor.fetchone()  # 获取一条记录

        if user is None:

            print('用户不存在')

            return None

        # 比对密码哈希

        if user['password'] == hash_password(password):

            print(f'欢迎回来,{username}!')

            return user

        else:

            print('密码错误')

            return None

    finally:

        cursor.close()

        conn.close()

# ── 测试 ──────────────────────────────────────

if __name__ == '__main__':

    register_user('alice', 'abc123', 'alice@example.com')

    user = login_user('alice', 'abc123')

    print(user)

第五章  商品管理(CRUD 操作)

CRUD 是四种基本数据库操作的缩写:Create(新增)、Read(查询)、Update(修改)、Delete(删除)。几乎所有软件都离不开这四种操作。

5.1 新增商品(Create)

# product_service.py

from db_config import get_connection

def add_product(name: str, price: float,

                stock: int, description: str = ''):

    """新增商品"""

    conn   = get_connection()

    cursor = conn.cursor()

    try:

        sql = """

            INSERT INTO products (name, price, stock, description)

            VALUES (%s, %s, %s, %s)

        """

        cursor.execute(sql, (name, price, stock, description))

        conn.commit()

        product_id = cursor.lastrowid  # 获取刚插入记录的ID

        print(f'商品已添加,ID = {product_id}')

        return product_id

    except Exception as e:

        conn.rollback()

        print(f'添加失败:{e}')

        return None

    finally:

        cursor.close()

        conn.close()

5.2 查询商品(Read)

def get_all_products():

    """获取所有商品列表"""

    conn   = get_connection()

    cursor = conn.cursor(dictionary=True)

    try:

        cursor.execute('SELECT * FROM products ORDER BY id')

        products = cursor.fetchall()

        return products

    finally:

        cursor.close()

        conn.close()

def get_product_by_id(product_id: int):

    """根据ID查询单个商品"""

    conn   = get_connection()

    cursor = conn.cursor(dictionary=True)

    try:

        cursor.execute('SELECT * FROM products WHERE id = %s',

                       (product_id,))

        return cursor.fetchone()  # 返回一条或 None

    finally:

        cursor.close()

        conn.close()

5.3 修改商品(Update)

def update_product_price(product_id: int, new_price: float):

    """修改商品价格"""

    conn   = get_connection()

    cursor = conn.cursor()

    try:

        sql = 'UPDATE products SET price = %s WHERE id = %s'

        cursor.execute(sql, (new_price, product_id))

        conn.commit()

        if cursor.rowcount > 0:

            print(f'商品 {product_id} 价格已更新为 {new_price}')

        else:

            print('商品不存在')

    except Exception as e:

        conn.rollback()

        print(f'更新失败:{e}')

    finally:

        cursor.close()

        conn.close()

5.4 删除商品(Delete)

def delete_product(product_id: int):

    """删除商品"""

    conn   = get_connection()

    cursor = conn.cursor()

    try:

        cursor.execute('DELETE FROM products WHERE id = %s',

                       (product_id,))

        conn.commit()

        if cursor.rowcount > 0:

            print(f'商品 {product_id} 已删除')

        else:

            print('商品不存在')

    except Exception as e:

        conn.rollback()

        print(f'删除失败:{e}')

    finally:

        cursor.close()

        conn.close()

� 提示  cursor.rowcount 表示上一条 SQL 影响了多少行数据,通过它可以判断操作是否真正修改了数据库。

第六章  订单管理

6.1 创建订单

创建订单是电商系统中最复杂的操作,涉及多张表的同时写入,以及库存扣减。必须使用事务(Transaction)保证原子性——要么全部成功,要么全部失败。

# order_service.py

from db_config import get_connection

def create_order(user_id: int, cart: list):

    """

    创建订单

    cart 格式:[{'product_id': 1, 'quantity': 2}, ...]

    """

    conn   = get_connection()

    cursor = conn.cursor(dictionary=True)

    try:

        total_amount = 0

        items_to_insert = []

        # 第一步:检查库存并计算总价

        for item in cart:

            cursor.execute(

                'SELECT id, name, price, stock FROM products WHERE id = %s',

                (item['product_id'],)

            )

            product = cursor.fetchone()

            if product is None:

                raise ValueError(f"商品 {item['product_id']} 不存在")

            if product['stock'] < item['quantity']:

                raise ValueError(f"{product['name']} 库存不足")

            total_amount += product['price'] * item['quantity']

            items_to_insert.append({

                'product_id': product['id'],

                'quantity':   item['quantity'],

                'unit_price': product['price'],

                'stock':      product['stock']

            })

        # 第二步:创建订单主记录

        cursor.execute(

            'INSERT INTO orders (user_id, total_amount) VALUES (%s, %s)',

            (user_id, total_amount)

        )

        order_id = cursor.lastrowid

        # 第三步:插入订单明细 + 扣减库存

        for it in items_to_insert:

            cursor.execute(

                'INSERT INTO order_items (order_id, product_id, quantity, unit_price)'

                ' VALUES (%s, %s, %s, %s)',

                (order_id, it['product_id'], it['quantity'], it['unit_price'])

            )

            cursor.execute(

                'UPDATE products SET stock = stock - %s WHERE id = %s',

                (it['quantity'], it['product_id'])

            )

        conn.commit()  # 全部成功才提交

        print(f'订单创建成功,订单ID = {order_id},总金额 = {total_amount:.2f}')

        return order_id

    except Exception as e:

        conn.rollback()  # 任何错误都回滚

        print(f'订单创建失败:{e}')

        return None

    finally:

        cursor.close()

        conn.close()

6.2 查询用户订单

def get_user_orders(user_id: int):

    """查询用户的所有订单(含明细)"""

    conn   = get_connection()

    cursor = conn.cursor(dictionary=True)

    try:

        # 查询订单列表

        cursor.execute(

            'SELECT * FROM orders WHERE user_id = %s ORDER BY created_at DESC',

            (user_id,)

        )

        orders = cursor.fetchall()

        # 为每个订单查询明细

        for order in orders:

            cursor.execute(

                '''SELECT oi.quantity, oi.unit_price, p.name

                   FROM order_items oi

                   JOIN products p ON oi.product_id = p.id

                   WHERE oi.order_id = %s''',

                (order['id'],)

            )

            order['items'] = cursor.fetchall()

        return orders

    finally:

        cursor.close()

        conn.close()

� 提示  这里使用了 JOIN 连接查询,将 order_items 和 products 两张表的数据合并,一次查询获取商品名称和价格,避免多次往返数据库。

第七章  完整运行示例

7.1 主程序入口

创建 main.py 将所有功能串联起来,模拟一次完整的购物流程:

# main.py

from user_service    import register_user, login_user

from product_service import add_product, get_all_products

from order_service   import create_order, get_user_orders

print('=' * 50)

print('  欢迎使用电商平台演示系统')

print('=' * 50)

# ── 1. 用户注册与登录 ──

register_user('张三', 'password123', 'zhangsan@example.com')

user = login_user('张三', 'password123')

# ── 2. 添加商品 ──

add_product('Python编程书',  59.90, 100, '零基础入门到精通')

add_product('机械键盘',      299.00,  50, '青轴,手感极佳')

add_product('USB集线器',      39.90, 200, '4口USB3.0')

# ── 3. 展示商品列表 ──

print('\n当前商品列表:')

for p in get_all_products():

    print(f"  [{p['id']}] {p['name']}  ¥{p['price']}  库存:{p['stock']}")

# ── 4. 下订单 ──

cart = [

    {'product_id': 1, 'quantity': 2},

    {'product_id': 3, 'quantity': 1},

]

order_id = create_order(user['id'], cart)

# ── 5. 查看订单 ──

print('\n我的订单:')

for order in get_user_orders(user['id']):

    print(f"  订单#{order['id']}  总价:¥{order['total_amount']}  状态:{order['status']}")

    for item in order['items']:

        print(f"    - {item['name']} x{item['quantity']}  @¥{item['unit_price']}")

7.2 项目文件结构

ecommerce/

├── db_config.py        # 数据库连接配置

├── user_service.py     # 用户注册/登录

├── product_service.py  # 商品 CRUD

├── order_service.py    # 订单管理

└── main.py             # 主程序入口

第八章  总结与延伸学习

知识点

掌握内容

数据库设计

四张核心表,主键/外键/约束的使用

Python 连接 MySQL

mysql-connector,连接对象与游标

SQL 防注入

使用 %s 占位符,避免字符串拼接

密码安全

SHA-256 单向加密,绝不存明文

CRUD 操作

商品的增删改查完整实现

事务处理

commit() 与 rollback() 保证数据完整性

JOIN 查询

多表联查获取关联数据

感谢阅读!如有问题欢迎在评论区留言交流 �

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐