【小学生都能看懂的Python入门教程】第八章:SQLAlchemy——与数据库的“心灵交流”:Python程序员的读心术秘籍

在这里插入图片描述

SQLAlchemy——与数据库的“心灵交流”:Python程序员的读心术秘籍

一、SQLAlchemy简介:数据库翻译官

1. 会读心术的数据库管家

SQLAlchemy是一个强大的ORM工具,就像:

  • 随身翻译官:把Python对象翻译成SQL语句
  • 智能机器人:自动处理繁琐的数据库操作
  • 代码魔术师:让数据库表变成Python类

核心超能力

superpowers = {
    "自动生成SQL": "不用手写SELECT * FROM",
    "多数据库支持": "SQLite/MySQL/PostgreSQL自由切换",
    "事务管理": "像银行转账一样保证数据安全",
    "延迟加载": "需要时才从数据库取数据"
}

冷知识:NASA在火星探测器项目中使用SQLAlchemy——说不定好奇号的数据库正在用你即将学到的知识!

二、安装SQLAlchemy:下载你的翻译官

1. 创建虚拟会议室(虚拟环境)

python -m venv sqlab  # 建立秘密基地
source sqlab/bin/activate  # 进入基地(Windows用`sqlab\Scripts\activate`)

2. 召唤翻译官

pip install sqlalchemy

安装过程小剧场

你:按下回车
电脑:正在下载心灵感应模块…
SQLAlchemy:安装完成!获得成就【数据库语者】

三、定义模型:把数据库表变成Python类

1. 创建待办事项模型

from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime

# 创建数据库连接引擎(心灵桥梁)
engine = create_engine('sqlite:///todos.db', echo=True)  
Base = declarative_base()

class Todo(Base):
    __tablename__ = 'todos'  # 数据库表名
    
    id = Column(Integer, primary_key=True)
    content = Column(String(100), nullable=False)  # 待办内容
    created_at = Column(DateTime, default=datetime.now)  # 创建时间
    is_done = Column(Integer, default=0)  # 0-未完成 1-已完成
    
    def __repr__(self):
        status = "✅" if self.is_done else "⏳"
        return f"<Todo {self.id}> {status} {self.content}"

# 创建数据库表(心灵共鸣仪式)
Base.metadata.create_all(engine)  

# 创建会话工厂(对话窗口)
Session = sessionmaker(bind=engine)

模型解剖课

  • create_engine:建立与数据库的量子纠缠
  • declarative_base:获得模型画布
  • Column:定义数据字段类型
  • sessionmaker:创建对话窗口

四、CRUD操作:与数据库的日常对话

1. Create:添加新待办

def add_todo(content):
    """添加新任务"""
    with Session() as session:
        new_todo = Todo(content=content)
        session.add(new_todo)  # 把便签贴到公告板
        session.commit()  # 保存变更
        print(f"添加成功!ID:{new_todo.id}")
        
add_todo("学习SQLAlchemy")  # 输出:添加成功!ID:1

2. Read:查询任务

def list_todos(show_all=False):
    """列出任务"""
    with Session() as session:
        query = session.query(Todo)
        if not show_all:
            query = query.filter_by(is_done=0)  # 只看未完成
            
        todos = query.order_by(Todo.created_at.desc()).all()
        print("\n待办清单:")
        for todo in todos:
            print(f"{todo.id}. {todo}")
            
list_todos()
# 输出:
# 1. <Todo 1> ⏳ 学习SQLAlchemy

3. Update:标记完成

def complete_todo(todo_id):
    """完成任务"""
    with Session() as session:
        todo = session.get(Todo, todo_id)  # 找到对应便签
        if todo:
            todo.is_done = 1  # 画上完成标记
            session.commit()
            print(f"任务{todo_id}已完成!")
        else:
            print("找不到这个任务,可能被外星人劫持了")

complete_todo(1)
list_todos()  # 任务1不再显示

4. Delete:删除任务

def delete_todo(todo_id):
    """删除任务"""
    with Session() as session:
        todo = session.get(Todo, todo_id)
        if todo:
            session.delete(todo)  # 撕掉便签
            session.commit()
            print(f"任务{todo_id}已进入黑洞")
        else:
            print("这个任务存在于平行宇宙")

delete_todo(1)  # 输出:任务1已进入黑洞

五、实战演练:智能待办管家

完整应用代码

from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import sys

# 初始化数据库连接
engine = create_engine('sqlite:///todos.db')
Base = declarative_base()

class Todo(Base):
    __tablename__ = 'todos'
    id = Column(Integer, primary_key=True)
    content = Column(String(100))
    created_at = Column(DateTime, default=datetime.now)
    is_done = Column(Integer, default=0)

Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)

def show_menu():
    print("\n=== 待办管家 ===")
    print("1. 添加任务")
    print("2. 列出任务")
    print("3. 完成任务")
    print("4. 删除任务")
    print("5. 退出系统")
    return input("请选择操作:")

def main():
    while True:
        choice = show_menu()
        
        if choice == '1':
            content = input("请输入任务内容:")
            with Session() as s:
                s.add(Todo(content=content))
                s.commit()
            print("任务已添加!")
            
        elif choice == '2':
            with Session() as s:
                todos = s.query(Todo).order_by(Todo.created_at).all()
                print("\n当前任务:")
                for t in todos:
                    status = "✅" if t.is_done else "⏳"
                    print(f"{t.id}. {status} {t.content}")
                    
        elif choice == '3':
            todo_id = input("请输入要完成的任务ID:")
            with Session() as s:
                todo = s.get(Todo, int(todo_id))
                if todo:
                    todo.is_done = 1
                    s.commit()
                    print("任务状态已更新!")
                else:
                    print("任务不存在")
                    
        elif choice == '4':
            todo_id = input("请输入要删除的任务ID:")
            with Session() as s:
                todo = s.get(Todo, int(todo_id))
                if todo:
                    s.delete(todo)
                    s.commit()
                    print("任务已消失!")
                else:
                    print("任务不在当前时间线")
                    
        elif choice == '5':
            print("期待下次为您服务!")
            sys.exit()
            
        else:
            print("输入错误,请重新选择")

if __name__ == "__main__":
    main()

六、SQLAlchemy冷知识档案馆

  1. 懒加载(Lazy Loading):默认不加载关联数据,直到真正访问时才查询
  2. 事务管理:用session.begin()开启事务,像银行转账一样保证原子性
  3. 混合属性:用@hybrid_property定义同时适用于Python和SQL的属性
  4. 数据库迁移:配合Alembic实现平滑升级(像给运行中的汽车换轮胎)

为什么选择SQLAlchemy?
当你想用Python的方式操作数据库,就像用母语交流而不是比手画脚时

七、常见问题诊疗室

症状Instance is not bound to a Session
药方:检查是否在会话外访问了数据库属性,确保使用上下文管理器

症状:N+1查询问题
药方:使用joinedload()进行预加载,避免多次查询

症状:忘记commit导致数据没保存
药方:用with Session() as session自动提交(需配置自动提交选项)

结语:从数据库文盲到心灵沟通者

现在你已经掌握:
✅ SQLAlchemy的核心哲学
✅ 模型定义的优雅方式
✅ CRUD操作的四种境界
✅ 完整待办应用的开发

当你能用面向对象的方式操控数据库时,就真正实现了与数据的"心灵交流"。记住,好的ORM使用就像母语对话——自然流畅,无需刻意思考语法结构。


课后彩蛋:在Todo类中添加以下方法:

def time_since_created(self):
    """显示任务创建时间差"""
    delta = datetime.now() - self.created_at
    return f"{delta.seconds//3600}小时前"
# 在列表显示时调用这个方法,看看效果
Python对象 ↔ ORM映射 ↔ 数据库表
posted @   爱上编程技术  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示