MySQL-综合应用(Python+Html)

基于python语言给出mysql调用数据库实现增删改查功能

Python 操作 MySQL 实现增删改查(CRUD)

这里使用 pymysql 库(Python 主流 MySQL 连接库),分环境准备、完整代码、分步讲解,附带数据表、异常处理、事务,可直接运行。

一、环境准备

1. 安装依赖

bash

运行

复制代码
pip install pymysql

2. 提前创建测试库和表

先在 MySQL 中执行下面 SQL,创建数据库、学生表:

sql

复制代码
-- 创建数据库
CREATE DATABASE IF NOT EXISTS python_mysql DEFAULT CHARSET utf8mb4;
USE python_mysql;

-- 学生表
CREATE TABLE student (
    sid INT PRIMARY KEY AUTO_INCREMENT,
    sname VARCHAR(20) NOT NULL,
    age INT,
    gender VARCHAR(10)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

二、完整代码(封装工具类 + 增删改查)

整体说明

  1. 封装数据库连接、关闭通用方法
  2. 实现:增、删、改、单条查询、多条查询
  3. 加入异常捕获、事务处理,防止数据出错

python

运行

复制代码
import pymysql
from pymysql import Error

# 数据库配置信息(修改为你自己的 MySQL 账号密码)
DB_CONFIG = {
    "host": "localhost",    # 数据库地址
    "user": "root",         # 用户名
    "password": "123456",   # 你的 MySQL 密码
    "database": "python_mysql",  # 数据库名
    "charset": "utf8mb4"
}


class MySQLUtil:
    """MySQL 工具类:连接、关闭、CRUD"""

    def __init__(self):
        # 初始化连接和游标
        self.connection = None
        self.cursor = None

    def connect(self):
        """建立数据库连接"""
        try:
            self.connection = pymysql.connect(**DB_CONFIG)
            # 创建游标(默认元组格式,也可使用 DictCursor 返回字典)
            self.cursor = self.connection.cursor(pymysql.cursors.DictCursor)
            print("数据库连接成功")
        except Error as e:
            print(f"连接失败:{e}")

    def close(self):
        """关闭游标和连接"""
        if self.cursor:
            self.cursor.close()
        if self.connection:
            self.connection.close()
        print("数据库连接已关闭")

    def insert_data(self, sname, age, gender):
        """新增数据"""
        try:
            sql = "INSERT INTO student(sname, age, gender) VALUES (%s, %s, %s)"
            self.cursor.execute(sql, (sname, age, gender))
            self.connection.commit()  # 提交事务
            print(f"新增成功,受影响行数:{self.cursor.rowcount}")
        except Error as e:
            self.connection.rollback()  # 出错回滚
            print(f"新增失败:{e}")

    def delete_data(self, sid):
        """根据学号删除数据"""
        try:
            sql = "DELETE FROM student WHERE sid = %s"
            self.cursor.execute(sql, sid)
            self.connection.commit()
            print(f"删除成功,受影响行数:{self.cursor.rowcount}")
        except Error as e:
            self.connection.rollback()
            print(f"删除失败:{e}")

    def update_data(self, sid, new_age):
        """根据学号更新年龄"""
        try:
            sql = "UPDATE student SET age = %s WHERE sid = %s"
            self.cursor.execute(sql, (new_age, sid))
            self.connection.commit()
            print(f"修改成功,受影响行数:{self.cursor.rowcount}")
        except Error as e:
            self.connection.rollback()
            print(f"修改失败:{e}")

    def query_one(self, sid):
        """查询单条数据(根据学号)"""
        try:
            sql = "SELECT * FROM student WHERE sid = %s"
            self.cursor.execute(sql, sid)
            result = self.cursor.fetchone()  # 获取一条结果
            print("单条查询结果:", result)
            return result
        except Error as e:
            print(f"查询失败:{e}")

    def query_all(self):
        """查询所有数据"""
        try:
            sql = "SELECT * FROM student"
            self.cursor.execute(sql)
            result = self.cursor.fetchall()  # 获取全部结果
            print("全部数据:")
            for row in result:
                print(row)
            return result
        except Error as e:
            print(f"查询失败:{e}")


if __name__ == "__main__":
    # 实例化工具类
    db = MySQLUtil()
    # 1. 连接数据库
    db.connect()

    # 2. 新增
    db.insert_data("张三", 18, "男")
    db.insert_data("李四", 19, "女")

    # 3. 查询所有
    db.query_all()

    # 4. 修改(把 sid=1 的年龄改为 20)
    db.update_data(1, 20)

    # 5. 单条查询
    db.query_one(1)

    # 6. 删除(删除 sid=2)
    db.delete_data(2)

    # 7. 再次查询所有
    db.query_all()

    # 8. 关闭连接
    db.close()

三、核心知识点讲解

1. 关键对象

  • connection:数据库连接对象,负责通信、事务提交 / 回滚
  • cursor :游标对象,执行 SQL、获取结果

2. 占位符说明

pymysql 统一使用 %s 作为参数占位符,不要拼接字符串,防止 SQL 注入。

python

运行

复制代码
# 安全写法(推荐)
sql = "INSERT INTO student(sname) VALUES (%s)"
cursor.execute(sql, ("张三",))

# 危险写法(禁止,SQL注入)
name = input()
sql = f"INSERT INTO student(sname) VALUES ('{name}')"

3. 事务操作(重点)

  • connection.commit()提交事务,增 / 删 / 改必须提交才生效
  • connection.rollback()事务回滚,SQL 执行异常时撤销操作,保证数据安全

4. 查询取值方法

  • fetchone():获取第一条查询结果
  • fetchall():获取全部查询结果
  • fetchmany(n):获取指定 n 条结果

5. 游标格式

  • DictCursor:返回字典,键为字段名,可读性强(示例使用)
  • 默认游标:返回元组,只有值没有字段名

四、分步运行效果说明

  1. 连接数据库 → 打印数据库连接成功
  2. 插入两条学生数据
  3. 查询全表,展示两条记录
  4. 修改 sid=1 年龄为 20
  5. 单独查询 sid=1 数据
  6. 删除 sid=2 记录
  7. 再次查询,只剩 sid=1 一条数据
  8. 关闭连接

五、拓展:简易原生写法(不封装类)

适合入门练习,代码更简短:

python

运行

复制代码
import pymysql

# 连接数据库
conn = pymysql.connect(
    host="localhost",
    user="root",
    password="123456",
    database="python_mysql",
    charset="utf8mb4"
)
cur = conn.cursor()

# 增
cur.execute("INSERT INTO student(sname,age) VALUES (%s,%s)", ("王五", 21))
conn.commit()

# 查
cur.execute("SELECT * FROM student")
print(cur.fetchall())

# 改
cur.execute("UPDATE student SET age=22 WHERE sid=3")
conn.commit()

# 删
cur.execute("DELETE FROM student WHERE sid=3")
conn.commit()

# 关闭
cur.close()
conn.close()

六、常见报错排查

  1. 连接失败:检查 MySQL 服务是否启动、账号 / 密码 / 库名是否正确
  2. 中文乱码 :连接时指定 charset="utf8mb4"
  3. 增删改无效果 :忘记执行 commit() 提交事务
  4. 外键 / 约束报错:参照之前外键规则,保证数据合法

给出html的前端页面部分,数据交互基于python实现

结合前面 Python + MySQL 后端,实现 HTML 前端页面 + 前后端数据交互 ,采用 Flask 轻量框架 (简单易上手,适合教学演示),完成学生信息增删改查全流程。

一、整体架构

  1. 后端:Python + Flask + pymysql(接口、数据库 CRUD)
  2. 前端:原生 HTML + 简单 CSS(页面表单、列表展示)
  3. 交互方式:前端通过 AJAX(JavaScript) 调用后端接口,实现无刷新数据交互

二、环境准备

  1. 安装依赖

bash

运行

复制代码
pip install pymysql flask
  1. 沿用之前 MySQL 库和表

sql

复制代码
CREATE DATABASE IF NOT EXISTS python_mysql DEFAULT CHARSET utf8mb4;
USE python_mysql;

CREATE TABLE student (
    sid INT PRIMARY KEY AUTO_INCREMENT,
    sname VARCHAR(20) NOT NULL,
    age INT,
    gender VARCHAR(10)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

三、后端代码(Flask + MySQL)

文件名:app.py提供 新增、查询、修改、删除 接口,统一接收前端请求。

python

运行

复制代码
from flask import Flask, request, jsonify
import pymysql
from pymysql import Error

app = Flask(__name__)

# 数据库配置
DB_CONFIG = {
    "host": "localhost",
    "user": "root",
    "password": "123456",  # 改成你的MySQL密码
    "database": "python_mysql",
    "charset": "utf8mb4"
}

# 数据库连接工具
def get_db_conn():
    return pymysql.connect(**DB_CONFIG)

# 1. 查询所有学生
@app.route('/get_student', methods=['GET'])
def get_student():
    conn = get_db_conn()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    try:
        cursor.execute("SELECT * FROM student")
        data = cursor.fetchall()
        return jsonify({"code": 200, "data": data})
    except Error as e:
        return jsonify({"code": 500, "msg": "查询失败"})
    finally:
        cursor.close()
        conn.close()

# 2. 新增学生
@app.route('/add_student', methods=['POST'])
def add_student():
    data = request.get_json()
    sname = data.get('sname')
    age = data.get('age')
    gender = data.get('gender')

    conn = get_db_conn()
    cursor = conn.cursor()
    try:
        sql = "INSERT INTO student(sname, age, gender) VALUES (%s, %s, %s)"
        cursor.execute(sql, (sname, age, gender))
        conn.commit()
        return jsonify({"code": 200, "msg": "新增成功"})
    except Error as e:
        conn.rollback()
        return jsonify({"code": 500, "msg": "新增失败"})
    finally:
        cursor.close()
        conn.close()

# 3. 修改学生年龄
@app.route('/update_student', methods=['POST'])
def update_student():
    data = request.get_json()
    sid = data.get('sid')
    age = data.get('age')

    conn = get_db_conn()
    cursor = conn.cursor()
    try:
        sql = "UPDATE student SET age = %s WHERE sid = %s"
        cursor.execute(sql, (age, sid))
        conn.commit()
        return jsonify({"code": 200, "msg": "修改成功"})
    except Error as e:
        conn.rollback()
        return jsonify({"code": 500, "msg": "修改失败"})
    finally:
        cursor.close()
        conn.close()

# 4. 删除学生
@app.route('/del_student', methods=['POST'])
def del_student():
    data = request.get_json()
    sid = data.get('sid')

    conn = get_db_conn()
    cursor = conn.cursor()
    try:
        sql = "DELETE FROM student WHERE sid = %s"
        cursor.execute(sql, sid)
        conn.commit()
        return jsonify({"code": 200, "msg": "删除成功"})
    except Error as e:
        conn.rollback()
        return jsonify({"code": 500, "msg": "删除失败"})
    finally:
        cursor.close()
        conn.close()

if __name__ == '__main__':
    # 启动后端服务
    app.run(debug=True)

四、前端 HTML 页面

文件名:index.html包含:新增表单、数据列表、修改 / 删除按钮、AJAX 交互,纯原生 JS,无需额外框架。

html

预览

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>学生信息管理</title>
    <style>
        *{margin: 10px;}
        table{border-collapse: collapse; width: 500px;}
        th,td{border: 1px solid #333; padding: 6px; text-align: center;}
        button{cursor: pointer; padding: 4px 10px;}
        .form-box{margin-bottom: 20px;}
    </style>
</head>
<body>
    <h2>学生信息管理系统</h2>

    <!-- 新增学生表单 -->
    <div class="form-box">
        姓名:<input type="text" id="sname" placeholder="请输入姓名">
        年龄:<input type="number" id="age" placeholder="请输入年龄">
        性别:<input type="text" id="gender" placeholder="请输入性别">
        <button onclick="addStudent()">新增</button>
    </div>

    <!-- 学生列表 -->
    <table>
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>操作</th>
        </tr>
        <tbody id="tableBody">
            <!-- 数据由JS动态渲染 -->
        </tbody>
    </table>

<script>
    // 页面加载完成自动查询数据
    window.onload = function(){
        getStudentList();
    }

    // 1. 查询所有学生
    function getStudentList(){
        fetch("/get_student")
        .then(res => res.json())
        .then(result => {
            let tbody = document.getElementById("tableBody");
            tbody.innerHTML = "";
            if(result.code === 200){
                let list = result.data;
                list.forEach(item => {
                    let tr = document.createElement("tr");
                    tr.innerHTML = `
                        <td>${item.sid}</td>
                        <td>${item.sname}</td>
                        <td>${item.age}</td>
                        <td>${item.gender}</td>
                        <td>
                            <button onclick="updateAge(${item.sid})">改年龄</button>
                            <button onclick="delStudent(${item.sid})">删除</button>
                        </td>
                    `;
                    tbody.appendChild(tr);
                })
            }
        })
    }

    // 2. 新增学生
    function addStudent(){
        let sname = document.getElementById("sname").value;
        let age = document.getElementById("age").value;
        let gender = document.getElementById("gender").value;

        fetch("/add_student",{
            method: "POST",
            headers: {"Content-Type":"application/json"},
            body: JSON.stringify({sname, age, gender})
        })
        .then(res => res.json())
        .then(result => {
            alert(result.msg);
            // 清空表单 + 刷新列表
            document.getElementById("sname").value = "";
            document.getElementById("age").value = "";
            document.getElementById("gender").value = "";
            getStudentList();
        })
    }

    // 3. 修改年龄
    function updateAge(sid){
        let newAge = prompt("请输入新年龄:");
        if(!newAge) return;
        fetch("/update_student",{
            method: "POST",
            headers: {"Content-Type":"application/json"},
            body: JSON.stringify({sid, age: newAge})
        })
        .then(res => res.json())
        .then(result => {
            alert(result.msg);
            getStudentList();
        })
    }

    // 4. 删除学生
    function delStudent(sid){
        if(!confirm("确定要删除该数据吗?")) return;
        fetch("/del_student",{
            method: "POST",
            headers: {"Content-Type":"application/json"},
            body: JSON.stringify({sid})
        })
        .then(res => res.json())
        .then(result => {
            alert(result.msg);
            getStudentList();
        })
    }
</script>
</body>
</html>

五、运行步骤(完整流程)

  1. 启动 MySQL 服务,保证数据库、数据表已创建
  2. 运行后端 app.py,控制台提示:Running on http://127.0.0.1:5000
  3. 用浏览器直接打开 index.html 文件
  4. 功能测试:
    • 输入姓名 / 年龄 / 性别,点击【新增】,数据存入 MySQL 并实时刷新列表
    • 点击【改年龄】,弹窗输入新年龄,完成数据修改
    • 点击【删除】,确认后删除数据库对应记录

六、核心交互说明

  1. 前后端通信
    • 后端 Flask 提供 REST 风格接口
    • 前端使用原生 fetch(AJAX)发送请求,传递 JSON 数据
  2. 数据流向前端表单 → JS 组装数据 → 调用后端接口 → Python 操作 MySQL → 结果返回前端 → 页面刷新
  3. 关键要点
    • 增 / 删 / 改 后端必须执行 commit() 提交事务
    • 前端发送 POST 请求,必须指定请求头 Content-Type:application/json
    • 所有数据库操作增加异常捕获,保证程序稳定

七、常见问题排查

  1. 页面无数据:检查 MySQL 是否启动、账号密码、数据库名是否正确
  2. 新增 / 修改无反应:查看后端控制台报错,优先检查 SQL 语句
  3. 跨域问题:本案例前后端同源,无需额外配置跨域;若分开部署需加装 flask-cors
  4. 中文乱码:确认数据库、连接配置均为 utf8mb4

flask

结合上一节前后端学生管理案例 ,精讲 Flask 基础 + 路由、请求、响应、模板使用,搭配代码示例,适配学习与实训。

一、Flask 简介

Flask 是 Python 轻量级 Web 框架,短小精悍、上手简单,适合快速开发接口、小型网站。

  • 核心特点:极简、灵活、扩展性强
  • 本项目用途:搭建 Web 接口,接收前端请求、操作数据库、返回数据

1. 安装

bash

运行

复制代码
pip install flask

二、Flask 最小入门示例(HelloWorld)

新建 app.py,最基础运行代码:

python

运行

复制代码
# 导入Flask类
from flask import Flask

# 实例化Flask对象,__name__代表当前模块名
app = Flask(__name__)

# 路由:访问根路径 / 执行下面函数
@app.route('/')
def index():
    return "Hello Flask!"

# 启动服务
if __name__ == '__main__':
    # debug=True 开启调试模式,代码修改自动重启
    app.run(debug=True)

运行后访问:http://127.0.0.1:5000,页面输出文本。


三、核心知识点(结合 CRUD 项目讲解)

1. 路由 @app.route()

作用:URL 地址 和 后端函数 绑定

基础用法

python

运行

复制代码
# 访问 http://127.0.0.1:5000/user
@app.route('/user')
def user_list():
    return "学生列表页面"

指定请求方式

默认支持 GET,如需接收 POST(前端提交数据必备):

python

运行

复制代码
# 仅允许 GET / POST 请求
@app.route('/add', methods=['GET', 'POST'])
def add():
    return "新增接口"

2. 请求对象 request

用于获取前端提交的数据,常用两种格式:

  1. JSON 数据(前后端分离 AJAX/fetch 主流用法)
  2. 表单 form 数据(传统 form 表单)

2.1 获取 JSON 数据(项目中使用)

前端用 fetchJSON,后端用 request.get_json() 接收:

python

运行

复制代码
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/test_json', methods=['POST'])
def test_json():
    # 获取前端json数据
    data = request.get_json()
    name = data.get("sname")
    age = data.get("age")
    return f"姓名:{name},年龄:{age}"

2.2 获取表单数据

python

运行

复制代码
@app.route('/test_form', methods=['POST'])
def test_form():
    name = request.form.get("sname")
    return name

3. 响应 jsonify

前端 AJAX 一般接收 JSON 格式数据 ,Flask 使用 jsonify() 快速构造标准 JSON 响应:

python

运行

复制代码
from flask import jsonify

@app.route('/get_data')
def get_data():
    # 字典转json返回给前端
    return jsonify({
        "code": 200,
        "msg": "查询成功",
        "data": [{"sid":1, "sname":"张三"}]
    })

4. 结合 MySQL 接口(复用之前学生项目核心)

整合 路由 + 请求 + MySQL,就是完整后端接口,拆分核心代码讲解:

python

运行

复制代码
from flask import Flask, request, jsonify
import pymysql

app = Flask(__name__)

# 数据库配置
DB_CONFIG = {
    "host": "localhost",
    "user": "root",
    "password": "123456",
    "database": "python_mysql",
    "charset": "utf8mb4"
}

# 数据库连接函数
def get_conn():
    return pymysql.connect(**DB_CONFIG)

# 1. 查询所有学生 GET接口
@app.route('/get_student', methods=['GET'])
def get_student():
    conn = get_conn()
    cur = conn.cursor(pymysql.cursors.DictCursor)
    cur.execute("SELECT * FROM student")
    res = cur.fetchall()
    cur.close()
    conn.close()
    return jsonify({"code":200, "data":res})

# 2. 新增学生 POST接口
@app.route('/add_student', methods=['POST'])
def add_student():
    data = request.get_json()
    sname = data["sname"]
    age = data["age"]
    gender = data["gender"]

    conn = get_conn()
    cur = conn.cursor()
    sql = "INSERT INTO student(sname,age,gender) VALUES(%s,%s,%s)"
    cur.execute(sql, (sname, age, gender))
    conn.commit()
    cur.close()
    conn.close()
    return jsonify({"code":200, "msg":"新增成功"})

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

四、Flask 模板(HTML 页面渲染,拓展知识点)

前面案例是前后端分离 (HTML 独立文件),Flask 也支持模板渲染,适合传统页面开发。

目录结构(固定格式)

plaintext

复制代码
项目文件夹
├── app.py          # 后端主程序
└── templates       # 必须命名为 templates
    └── index.html  # 前端页面

1. 后端渲染模板

python

运行

复制代码
from flask import Flask, render_template

app = Flask(__name__)

# 访问 / 自动渲染 templates/index.html
@app.route('/')
def index():
    # 向页面传变量
    name = "张三"
    return render_template("index.html", username=name)

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

2. 模板中接收变量(index.html)

html

预览

复制代码
<!DOCTYPE html>
<html>
<body>
    <h3>欢迎 {{ username }}</h3>
</body>
</html>

五、启动与运行说明

  1. 执行 python app.py 启动服务
  2. 默认地址:http://127.0.0.1:5000
  3. debug=True:代码修改后自动重启服务,开发必备,生产环境关闭

六、常用报错 & 解决

  1. 端口被占用

python

运行

复制代码
# 修改端口
app.run(port=8080, debug=True)
  1. 前端 POST 接收不到数据
  • 前端没设置 Content-Type: application/json
  • 后端误用 request.form 接收 JSON,改用 request.get_json()
  1. 中文乱码 数据库、连接字符串统一使用 utf8mb4

七、整体流程总结(考试 / 实训简答)

  1. Flask 编写路由,定义接口地址与请求方式;
  2. 前端发起 GET/POST 请求,传递参数;
  3. 后端通过 request 获取前端数据;
  4. 结合 pymysql 操作 MySQL 完成增删改查;
  5. 使用 jsonify 将结果转为 JSON 返回前端;
  6. 前端 JS 解析 JSON,动态渲染页面。
    self.connection = pymysql.connect(**DB_CONFIG)

这行代码是 Python 使用 PyMySQL 连接 MySQL 数据库 的核心代码,我给你讲清楚它的作用、参数含义,以及和你刚才问的字符集有什么关系。


一、代码作用

python

运行

复制代码
self.connection = pymysql.connect(**DB_CONFIG)

简单解释

  1. pymysql.connect() PyMySQL 库提供的创建数据库连接的方法。
  2. **DB_CONFIG 把字典 DB_CONFIG 里的配置自动拆分成关键字参数传给 connect。
  3. self.connection 把创建好的数据库连接对象保存下来,后面执行 SQL 都会用它。

二、DB_CONFIG 长什么样?(最关键)

这行代码能运行,前提是你前面定义了 DB_CONFIG 字典,通常长这样:

python

运行

复制代码
DB_CONFIG = {
    "host": "localhost",      # 数据库地址
    "port": 3306,             # 端口
    "user": "root",           # 用户名
    "password": "123456",     # 密码
    "database": "test_db",    # 要连接的库名
    "charset": "utf8mb4"      # 字符集(非常重要!)
}

三、和你刚才问的「字符集」直接相关

这行代码里 charset 必须和 MySQL 数据库的字符集一致 ,否则会出现中文乱码

正确写法

python

运行

复制代码
"charset": "utf8mb4"   # 推荐,支持 emoji

错误写法

python

运行

复制代码
"charset": "utf-8"   # 错!MySQL 里叫 utf8mb4,不是 utf-8

四、完整可运行示例

python

运行

复制代码
import pymysql

# 数据库配置
DB_CONFIG = {
    "host": "127.0.0.1",
    "port": 3306,
    "user": "root",
    "password": "你的密码",
    "database": "你的库名",
    "charset": "utf8mb4"  # 字符集必须写对
}

# 创建连接
self.connection = pymysql.connect(**DB_CONFIG)

# 测试连接是否成功
print("数据库连接成功!")

五、常见问题

  1. 报错:Unknown charset 'utf-8' 改成 utf8mb4 即可。

  2. 中文乱码 确保:

    • 代码里 charset=utf8mb4
    • 数据库字符集也是 utf8mb4
  3. 连接失败 检查 host、port、user、password、database 是否正确。


总结

  • **DB_CONFIG = 自动解包数据库配置
  • charset="utf8mb4" = 防止中文乱码、支持 emoji(最推荐)
  • 这行代码的作用就是拿到一个可用的 MySQL 连接对象

如果你需要,我还能帮你写完整的增删改查工具类

解释python (**字典)语法

Python ** 字典 语法(超通俗解释)

**字典 是 Python 里的关键字参数解包 ,专门用来把字典里的键值对 ,自动变成函数的参数名=参数值形式。


1. 一句话看懂

python

运行

复制代码
函数(**字典)

= 把字典拆成一堆参数,直接喂给函数


2. 超简单例子

你有一个字典:

python

运行

复制代码
info = {
    "name": "小明",
    "age": 20
}

有一个函数:

python

运行

复制代码
def show(name, age):
    print(name, age)

用 ** 解包,一行搞定传参:

python

运行

复制代码
show(**info)
# 等价于:show(name="小明", age=20)

结果:

plaintext

复制代码
小明 20

3. 回到你数据库代码

你写的:

python

运行

复制代码
self.connection = pymysql.connect(**DB_CONFIG)

等价于 手动写一长串参数

python

运行

复制代码
self.connection = pymysql.connect(
    host="localhost",
    port=3306,
    user="root",
    password="123456",
    database="test",
    charset="utf8mb4"
)

**DB_CONFIG 就是帮你自动展开字典,代码更干净、更好维护。


4. 必须满足的规则(很重要)

  1. 字典的 key 必须和函数参数名完全一样
    • 函数要 host,字典就必须写 "host"
    • 写错名字会直接报错
  2. 不能多传、不能少传必填参数
  3. 只能用在函数调用里

5. 小补充:* 和 ** 的区别

  • *列表:解包位置参数
  • **字典:解包关键字参数(参数名 = 值)

总结

  • **字典 = 字典 → 自动拆成 参数名 = 参数值
  • 让代码更简洁,不用手写一长串参数
  • 你数据库那行代码就是用它批量传连接信息

需要我再给你几个实战小练习巩固一下吗?

好的

练习 1:基础 ** 解包

python

运行

复制代码
def connect_db(host, user, pwd):
    print(f"地址:{host},账号:{user},密码:{pwd}")

cfg = {"host":"127.0.0.1", "user":"root", "pwd":"123456"}
# **把字典拆成 host=...,user=...,pwd=...
connect_db(**cfg)

运行等价:connect_db(host="127.0.0.1",user="root",pwd="123456")

练习 2:混合传参(固定参数 + ** 字典)

python

运行

复制代码
def connect_db(host, user, pwd, charset):
    print(host, user, pwd, charset)

cfg = {"user":"root", "pwd":"123456"}
# 固定写host,剩余从字典解包
connect_db("localhost",**cfg, charset="utf8mb4")

练习 3:函数定义时 **kwargs(收集多余关键字参数)

python

运行

复制代码
def test(a,**kwargs):
    print(a)
    print(kwargs) # 多余参数自动装进字典

test(100,name="张三",age=18)
# kwargs = {"name":"张三","age":18}

练习 4:pymysql 场景仿写(对应你原来代码)

python

运行

复制代码
def connect(**config):
    print(config["host"],config["charset"])

DB_CONFIG = {
    "host":"127.0.0.1",
    "port":3306,
    "user":"root",
    "charset":"utf8mb4"
}
connect(**DB_CONFIG)

关键口诀

  1. 函数调用里:**dict → 字典拆成 key=value 实参
  2. 函数形参:**kwargs → 零散 key=value 打包成字典
    py连接数据库创建游标的含义与作用

我用最通俗、最直白 的方式给你讲清楚: Python 连接 MySQL 后,为什么要创建游标(cursor)?它到底是干嘛的?


一、一句话解释

游标(cursor)就是你和数据库之间的 "传令兵 / 执行器"。

  • 你有了 connection(连接)= 你打通了到数据库的路
  • 但你不能直接对着路发号施令
  • 必须创建一个 cursor(游标) ,让它帮你执行 SQL、拿结果

二、官方一点的解释

python

运行

复制代码
# 1. 创建连接(修路)
conn = pymysql.connect(**DB_CONFIG)

# 2. 创建游标(派传令兵)
cursor = conn.cursor()  # 这就是创建游标的代码

# 3. 游标执行SQL(传令兵去干活)
cursor.execute("SELECT * FROM user")

# 4. 游标拿回数据(传令兵把结果带回来)
data = cursor.fetchall()

游标到底做什么?(核心作用)

  1. 执行 SQL 语句 SELECT / INSERT / UPDATE / DELETE 都必须通过游标执行。

  2. 接收 / 存储查询结果 数据库返回的数据,先放在游标里,你再从游标取。

  3. 控制事务 提交、回滚都和它相关。

  4. 遍历查询结果 像指针一样,一行一行读取数据。


三、超形象比喻(一看就懂)

  • 连接(connection) = 电话线
  • 游标(cursor) = 电话听筒
  • 你不拿起听筒,就不能说话、不能听对方声音
  • 不创建游标,就不能执行 SQL、不能拿数据

四、创建游标的标准代码

python

运行

复制代码
import pymysql

DB_CONFIG = {
    "host": "localhost",
    "user": "root",
    "password": "123456",
    "database": "test",
    "charset": "utf8mb4"
}

# 1. 建立连接
conn = pymysql.connect(**DB_CONFIG)

# 2. 创建游标 【重要步骤】
cursor = conn.cursor()

# 3. 用游标执行SQL
cursor.execute("SELECT * FROM user")

# 4. 获取结果
result = cursor.fetchall()
print(result)

# 5. 关闭游标和连接
cursor.close()
conn.close()

五、最常用的游标方法

python

运行

复制代码
cursor.execute(sql)          # 执行SQL
cursor.fetchone()            # 拿1条数据
cursor.fetchall()            # 拿全部数据
cursor.fetchmany(n)          # 拿n条数据
cursor.close()               # 关闭游标

六、你必须记住的结论

  1. 有连接不一定能操作数据库
  2. 有游标才能操作数据库
  3. 一个连接可以创建多个游标
  4. 用完一定要关闭游标(好习惯)

总结

  • connection = 建立到数据库的连接
  • cursor = 真正执行 SQL、获取数据的工具
  • 没有游标,你有连接也无法操作数据库
    pymysql.cursors.DictCursor

一句话讲懂 pymysql.cursors.DictCursor

它就是让数据库查询结果直接返回【字典】而不是【元组】 的游标类型,写代码更方便、更直观


1. 普通游标 vs DictCursor

① 普通游标(默认)

python

运行

复制代码
cursor = conn.cursor()
cursor.execute("SELECT id,name FROM user")
print(cursor.fetchone())

返回结果:元组 tuple

plaintext

复制代码
(1, "张三")

取值必须用下标

python

运行

复制代码
data[0]  # id
data[1]  # name

缺点:不知道下标对应哪个字段,容易写错。


② DictCursor 字典游标(推荐)

python

运行

复制代码
from pymysql.cursors import DictCursor
cursor = conn.cursor(cursor=DictCursor)

返回结果:字典 dict

plaintext

复制代码
{"id": 1, "name": "张三"}

取值用字段名,一目了然:

python

运行

复制代码
data["id"]
data["name"]

2. 完整代码示例(你直接复制就能用)

python

运行

复制代码
import pymysql
from pymysql.cursors import DictCursor  # 导入

# 数据库配置
DB_CONFIG = {
    "host": "localhost",
    "user": "root",
    "password": "123456",
    "database": "test",
    "charset": "utf8mb4"
}

# 1. 建立连接
conn = pymysql.connect(**DB_CONFIG)

# 2. 创建【字典游标】 ✅
cursor = conn.cursor(cursor=DictCursor)

# 3. 查询
cursor.execute("SELECT id,name,age FROM user WHERE id=1")

# 4. 获取结果(字典格式)
result = cursor.fetchone()
print(result)          # {'id':1, 'name':'张三', 'age':20}
print(result["name"])  # 直接用字段名取值 ✅

# 关闭
cursor.close()
conn.close()

3. 为什么推荐用 DictCursor?

  1. 代码可读性极高 data["name"]data[1] 清楚一万倍

  2. 不用记字段顺序

  3. 返回多条数据 = 列表里包字典 (最常用)

    python

    运行

    复制代码
    [
        {"id":1,"name":"张三"},
        {"id":2,"name":"李四"}
    ]
  4. 直接可以转 JSON(接口开发必备)


4. 最简单写法(不用单独导入)

你也可以这样写,更短:

python

运行

复制代码
cursor = conn.cursor(pymysql.cursors.DictCursor)

总结

  • 普通游标 → 返回 (1, "张三") 元组
  • DictCursor → 返回 {"id":1, "name":"张三"} 字典
  • 实际开发 99% 都用 DictCursor

代码解析 + 完善优化 + 配套函数实现

这段 JS 代码作用:通过 fetch 请求后端接口 /get_student 获取学生列表,动态渲染到表格 tbody 中,绑定【修改年龄】【删除】按钮点击事件

一、原代码说明

javascript

运行

复制代码
function getStudentList(){
    fetch("/get_student") // 请求后端学生接口
    .then(res => res.json()) // 响应转JSON
    .then(result => {
        let tbody = document.getElementById("tableBody");
        tbody.innerHTML = ""; // 清空表格旧数据
        if(result.code === 200){ // 后端返回成功
            let list = result.data; // 学生数组
            list.forEach(item => { // 遍历学生
                let tr = document.createElement("tr");
                tr.innerHTML = `
                    <td>${item.sid}</td>
                    <td>${item.sname}</td>
                    <td>${item.age}</td>
                    <td>${item.gender}</td>
                    <td>
                        <button onclick="updateAge(${item.sid})">改年龄</button>
                        <button onclick="delStudent(${item.sid})">删除</button>
                    </td>
                `;
                tbody.appendChild(tr); // 添加行到表格
            })
        }
    })
}

字段说明

  • sid:学生编号(主键,数字)
  • sname:学生姓名
  • age:年龄
  • gender:性别
  • 按钮绑定全局方法:updateAge(sid) 修改年龄、delStudent(sid) 删除学生

二、配套缺失函数(补充修改年龄 + 删除学生)

javascript

运行

复制代码
// 删除学生
function delStudent(sid) {
    if(!confirm("确定删除该学生?")) return;
    fetch(`/del_student?sid=${sid}`, {method:"DELETE"})
    .then(res=>res.json())
    .then(res=>{
        if(res.code===200){
            alert("删除成功");
            getStudentList(); // 刷新列表
        }else{
            alert(res.msg||"删除失败");
        }
    })
}

// 修改年龄
function updateAge(sid) {
    let newAge = prompt("请输入新年龄:");
    if(!newAge || isNaN(newAge)) return alert("年龄格式错误");
    fetch(`/update_age?sid=${sid}&age=${newAge}`,{method:"PUT"})
    .then(res=>res.json())
    .then(res=>{
        if(res.code===200){
            alert("修改成功");
            getStudentList();
        }else{
            alert(res.msg||"修改失败");
        }
    })
}

三、配套 HTML 表格结构

html

预览

复制代码
<table border="1" cellpadding="6">
    <thead>
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody id="tableBody"></tbody>
</table>

<!-- 页面加载自动渲染列表 -->
<script>
window.onload = getStudentList;
// 上面三个JS函数放这里
</script>

四、优化建议(可选优化写法,避免 onclick 全局污染)

原代码 onclick="updateAge(${item.sid})" 依赖全局函数,推荐使用事件绑定代替:

js

复制代码
// 替换tr内按钮写法,改用addEventListener
let btnEdit = document.createElement("button");
btnEdit.innerText = "改年龄";
btnEdit.onclick = ()=>updateAge(item.sid);

let btnDel = document.createElement("button");
btnDel.innerText = "删除";
btnDel.onclick = ()=>delStudent(item.sid);

let td = document.createElement("td");
td.append(btnEdit, btnDel);
tr.append(td);

五、后端接口约定(前后端统一)

表格

接口 请求方式 参数 功能
/get_student GET 查询所有学生
/del_student DELETE sid 根据学号删除
/update_age PUT sid、age 修改学生年龄
后端返回格式统一:{code:200, data:[...], msg:"xxx"}

需要我帮你补全后端 Python/Java 接口代码吗?

fetch

fetch 详解(结合你上面学生列表代码)

fetch 是浏览器原生 AJAX,用来发网络请求(GET/POST/PUT/DELETE),不用引 jQuery。

1. 基础语法

js

复制代码
fetch(请求地址, [配置项])
.then(响应对象 => 响应.json()) // 解析JSON
.then(data => {}) // 拿到后端数据
.catch(err=>{}) // 捕获网络错误

① 默认 GET 请求(你原来代码就是 GET)

js

复制代码
// GET 无参数
fetch("/get_student")
.then(res=>res.json())
.then(result=>{...})

② GET 拼接参数

js

复制代码
// /del_student?sid=1
fetch(`/del_student?sid=${sid}`)

③ POST / PUT / DELETE(需要配置 method、body)

js

复制代码
fetch('/add_student',{
  method:'POST', // PUT/DELETE
  headers:{
    'Content-Type':'application/json'
  },
  body: JSON.stringify({
    sname:'张三',age:18,gender:'男'
  })
})
.then(res=>res.json())

2. 拆解你原有代码的 fetch 流程

js

复制代码
fetch("/get_student")
// 第一步:拿到http原始响应
.then(res => res.json()) 
// res.json():把后端返回的json字符串→js对象(异步Promise)
.then(result => {
    // result就是后端 {code:200,data:[学生数组]}
})

注意:fetch**只有网络断网才进catch**,http 404/500不会报错,需要手动判断 res.ok`

js

复制代码
fetch('/xxx')
.then(res=>{
  if(!res.ok) throw new Error('请求失败'+res.status)
  return res.json()
})

3. async/await 简化写法(推荐替换原来链式 then)

js

复制代码
async function getStudentList(){
  try{
    let res = await fetch("/get_student")
    let result = await res.json()
    let tbody = document.getElementById("tableBody")
    tbody.innerHTML=""
    if(result.code===200){
      let list=result.data
      // 渲染表格...
    }
  }catch(err){
    console.error('请求出错',err)
  }
}

4. 常用配置项汇总

js

复制代码
fetch(url,{
  method:"GET|POST|PUT|DELETE",
  headers:{
    "Content-Type":"application/json"
  },
  body:JSON.stringify(数据), // POST/PUT传参
  credentials:"include" // 携带cookie
})
相关推荐
噜噜噜阿鲁~1 小时前
python学习笔记 | 11.4、面向对象高级编程-定制类
笔记·python·学习
站大爷IP1 小时前
Python闭包变量作用域踩坑实录,原来我们都想错了
python
XZ-0700011 小时前
MySQL-聚簇索引
数据库·mysql
zzj_2626101 小时前
实验七 Python 文件操作与异常处理
开发语言·python
菜到离谱但坚持1 小时前
零门槛学LangChain:AI开发从入门到实战
python·langchain·prompt·rag
databook1 小时前
一次函数图像工厂:用 SymPy 自动生成 y=kx+b 对比动画
python·数学·动效
测试老哥1 小时前
接口测试详解
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
geovindu1 小时前
python: N-Barrier Pattern
开发语言·python·设计模式·屏障模式
浮生望2 小时前
Python 入门 + 调用 LLM API:从 List 切片到商品文案生成
python