SQLAlchemy实战使用总结(通俗易懂)!!!

目录

简介

基本用法

安装

连接数据库

配置信息

 创建引擎并连接数据库

创建ORM模型并映射到数据建库中

增删改查(CRUD)操作

新增

单条新增:

批量新增:

删除

修改

 单条更新:

 批量更新:

查询

 查询所有数据

 指定查询列

 获取返回数据的第一行

 查询数据 指定查询数据列 加入别名

原生SQL查询

表达式筛选条件

原生SQL筛选条件

筛选条件格式

字符串匹配方式筛选条件 并使用 order_by进行排序

and or使用

复杂查询

查询语句

排序

通配符

限制(切片)

分组

between in使用

类型转换

dict_to_object

db_tuple_to_dict

model_to_dict

res_copy_model_to_dest(修改的时候会用到)


简介

        SQLAlchemy是用Python编程语言开发的一个开源项目。它提供了SQL工具包和ORM(对象关系映射)工具,使用MIT许可证发行。

        SQLAlchemy最初在2006年2月发行,发行后便很快的成为Python社区中最广泛使用的ORM工具之一,丝毫不亚于Django自带的ORM框架。

        SQLAlchemy采用简单的Python语言,提供高效和高性能的数据库访问,实现了完整的企业级持久模型。它的理念是,SQL数据库的量级和性能比对象集合重要,而对象集合的抽象又重要于表和行。


以上都是比较官方的说法,帮助大家了解一下SQLAlchemy。了解了解就可。

基本用法

安装

安装sqlalchemy

pip3 install sqlalchemy
pip3 install pymysql

本文使用MySQL作为数据库,使用pymysql作为驱动,因此需要安装pymysql

连接数据库

配置信息

在连接数据库前,需要使用到一些配置信息,然后把它们组合成满足以下条件的字符串:

dialect+driver://username:password@host:port/database

例:mysql+pymysql://root:root@192.168.105.110:30306/testDataBase

建议将配置信息放到你的配置文件中,如config.py

  • dialect:数据库,如:sqlite、mysql、oracle等
  • driver:数据库驱动,用于连接数据库的,本文使用pymysql
  • username:用户名
  • password:密码
  • host:IP地址
  • port:端口
  • database:数据库

 创建引擎并连接数据库

from sqlalchemy import create_engine
from config import DB_URI


engine = create_engine(DB_URI)  # 创建引擎
conn = engine.connect()  # 连接
result = conn.execute('SELECT 1')  # 执行SQL
print(result.fetchone())  
conn.close()  # 关闭连接

创建ORM模型并映射到数据建库中

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from config import DB_URI

engine = create_engine(DB_URI)
Base = declarative_base(engine)  # SQLORM基类
session = sessionmaker(engine)()  # 构建session对象


class Student(Base):
    __tablename__ = 'student'  # 表名
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50))
    age = Column(Integer)
    sex = Column(String(10))


Base.metadata.create_all()  # 将模型映射到数据库中

执行上面代码,将会在数据库中生成对应的映射表student。

增删改查(CRUD)操作

        新增和修改的时候可能会遇到类型错误问题,可以参考下面的类型转换。

新增

注意:主要看使用的方法以及传入的参数,像开发session以及命名是什么,用自己框架的获取session对象就可以。

单条新增:

# 1.首先导入之间做好的ORM 对象 User
from my_create_table import User
# 2.使用Users ORM模型创建一条数据
user1 = User(name="wang")
# 在db_session会话中添加一条 UserORM模型创建的数据
db_session.add(user1)
# 使用 db_session 会话提交 , 这里的提交是指将db_session中的所有指令一次性提交
db_session.commit()

批量新增:

 方法一:(最常用,但是执行时间不算快)

# 方法一:
user2 = User(name="张三")
user3 = User(name="王五")
db_session.add(user2)
db_session.add(user3)
db_session.commit()
# 之前说过commit是将db_session中的所有指令一次性提交,现在的db_session中至少有两条指令user2和user3
db_session.close()
#关闭会话

 方法二:

# 方法二:
user_list = [
    User(name="wang1"),
    User(name="wang2"),
    User(name="wang3")
]
db_session.add_all(user_list)
db_session.commit()

db_session.close()

 方法三:(执行时间最短排名:4)

db_session.bulk_save_objects(
            [
                Customer(name="NAME " + str(i))
                for i in xrange(min(10000, n1))
            ]
        )
db_session.commit()

 方法四:(执行时间最短排名:3)

db_session.bulk_insert_mappings(
            Customer,
            [
                dict(name="NAME " + str(i))
                for i in xrange(min(10000, n1))
            ]
        )
 db_session.commit()

方法五:(执行时间最短排名:2)

engine = create_engine(dbname, echo=False)


engine.execute(
        Customer.__table__.insert(),
        [{"name": 'NAME ' + str(i)} for i in xrange(n)]
    )  ##==> engine.execute('insert into ttable (name) values ("NAME"), ("NAME2")')

方法六:(执行时间最短排名:1)

def init_sqlite3(dbname):
    conn = sqlite3.connect(dbname)
    c = conn.cursor()
    c.execute("DROP TABLE IF EXISTS customer")
    c.execute(
        "CREATE TABLE customer (id INTEGER NOT NULL, "
        "name VARCHAR(255), PRIMARY KEY(id))")
    conn.commit()
    return conn
 
 
def test_sqlite3(n=100000, dbname='sqlite3.db'):
    conn = init_sqlite3(dbname)
    c = conn.cursor()
    t0 = time.time()
    for i in xrange(n):
        row = ('NAME ' + str(i),)
        c.execute("INSERT INTO customer (name) VALUES (?)", row)
    conn.commit()

删除

# 删除
class_info = db_session.query(ClassTable).filter(ClassTable.name=="OldBoyS1").first()
db_session.query(Student).filter(Student.class_id == class_info.id).delete()
db_session.commit()

db_session.close()
user = UserSample()
db.session.query(UserSample).filter_by(id=user.id).delete()
db.session.commit()
db.session.close()

修改

 单条更新:

# UPDATE user SET name="NBDragon" WHERE id=20 更新一条数据
# 语法是这样的 :
# 使用 db_session 执行User表 query(User) 筛选 User.id = 20 的数据 filter(User.id == 20)
# 将name字段的值改为NBDragon update({"name":"NBDragon"})
res = db_session.query(User).filter(User.id == 20).update({"name":"NBDragon"})
print(res) # 1 res就是我们当前这句更新语句所更新的行数
# 注意注意注意
# 这里一定要将db_session中的执行语句进行提交,因为你这是要对数据中的数据进行操作
# 数据库中 增 改 删 都是操作,也就是说执行以上三种操作的时候一定要commit
db_session.commit()
db_session.close()
#关闭会话

 批量更新:

# 更新多条
res = db_session.query(User).filter(User.id <= 20).update({"name":"NBDragon"})
print(res) # 6 res就是我们当前这句更新语句所更新的行数
db_session.commit()
db_session.close()
#关闭会话

查询

 查询所有数据

# 查询所有数据
res = db_session.query(User).all()

 指定查询列

# query的时候我们不在使用User ORM对象,而是使用User.name来对内容进行选取
user_list = db_session.query(User.name).all()

 获取返回数据的第一行

# 获取返回数据的第一行
res = db_session.query(User).first()

 查询数据 指定查询数据列 加入别名

# 查询数据 指定查询数据列 加入别名
res = db_session.query(User.name.label('username'), User.id).first()

原生SQL查询

#原生SQL查询
res = db_session.query(User).from_statement(text("SELECT * FROM User where name=:name")).params(name='wang').all()

表达式筛选条件

# 表达式筛选条件
res = db_session.query(User).filter(User.name == "wang").all()

原生SQL筛选条件

# 原生SQL筛选条件
r4 = db_session.query(User).filter_by(name='wang').all()
r5 = db_session.query(User).filter_by(name='wang').first()

筛选条件格式

# 筛选条件格式
# filter:
user_list = db_session.query(User).filter(User.name == "wang").all()
user_list = db_session.query(User).filter(User.name == "wang").first()

# filter_by:
user_list = db_session.query(User).filter_by(name="wang").all()
user_list = db_session.query(User).filter_by(name="wang").first()

字符串匹配方式筛选条件 并使用 order_by进行排序

# 字符串匹配方式筛选条件 并使用 order_by进行排序
res = db_session.query(User).filter(text("id<:value and name=:name")).params(value=224, name='wang').order_by(User.id).all()

and or使用

# and or
from sqlalchemy.sql import and_ , or_
res = db_session.query(User).filter(and_(User.id > 3, User.name == 'wang')).all()
ret = db_session.query(User).filter(or_(User.id < 2, User.name == 'wang')).all()

复杂查询

# 复杂查询
from sqlalchemy.sql import text
user_list = db_session.query(User).filter(text("id<:value and name=:name")).params(value=3,name="wang")

查询语句

# 查询语句
data = db_session.execute('select * from t_user where name=:value', params={"value": 'abc'})

row = data.fetchone()  # 取第一条
print(row.id)  # 取主键
print(row.name)  # 取字段

rows = data.fetchall()  # 取所有数据
for row in rows:
    print(row.id, row.name)
print(data.rowcount)  # 取条数

排序

# 排序 :
user_list = db_session.query(User).order_by(User.id).all()
user_list = db_session.query(User).order_by(User.id.desc()).all()

通配符

# 通配符
ret = db_session.query(User).filter(User.name.like('e%')).all()
ret = db_session.query(User).filter(~User.name.like('e%')).all()

限制(切片)

# 限制
ret = db_session.query(User)[1:2]

分组

from sqlalchemy.sql import func

ret = db_session.query(User).group_by(User.extra).all()
ret = db_session.query(
    func.max(User.id),
    func.sum(User.id),
    func.min(User.id)).group_by(User.name).all()

ret = db_session.query(
    func.max(User.id),
    func.sum(User.id),
    func.min(User.id)).group_by(User.name).having(func.min(User.id) >2).all()

between in使用

# between使用
ret = session.query(User).filter(User.id.between(1, 3), User.name == 'wang').all() # between 大于1小于3的


# in使用
ret = session.query(User).filter(User.id.in_([1,3,4])).all() # in_([1,3,4]) 只查询id等于1,3,4的
ret = session.query(User).filter(~User.id.in_([1,3,4])).all() # ~xxxx.in_([1,3,4]) 查询不等于1,3,4的
ret = session.query(User).filter(User.id.in_(session.query(User.id).filter_by(name='wang'))).all() 子查询

类型转换

dict_to_object

def dict_to_object(dict_data, obj):
    dic2class(dict_data, obj)


def dic2class(py_data, obj):
    for name in [name for name in dir(obj) if not name.startswith('_')]:
        if name not in py_data:
            setattr(obj, name, None)
        else:
            value = getattr(obj, name)
            setattr(obj, name, set_value(value, py_data[name]))


def set_value(value, py_data):
    if str(type(value)).__contains__('.'):
        # value 为自定义类
        dic2class(py_data, value)
    elif str(type(value)) == "<class 'list'>":
        # value为列表
        if value.__len__() == 0:
            # value列表中没有元素,无法确认类型
            value = py_data
        else:
            # value列表中有元素,以第一个元素类型为准
            child_value_type = type(value[0])
            value.clear()
            for child_py_data in py_data:
                child_value = child_value_type()
                child_value = set_value(child_value, child_py_data)
                value.append(child_value)
    else:
        value = py_data
    return value

db_tuple_to_dict

def db_tuple_to_dict(resultproxy):
    d, a = {}, []
    for rowproxy in resultproxy:
        for column, value in rowproxy.items():
            d = {**d, **{column: value}}
        a.append(d)
    return a

model_to_dict

def model_to_dict(obj):
    dic = {}
    dic_columns = obj.__table__.columns
    # 保证都是字符串和数字
    types = [str, int, float, bool]
    # 注意,obj.__dict__会在commit后被作为过期对象清空dict,所以保险的办法还是用columns
    for k, tmp in dic_columns.items():
        # k=nick,tmp=usergroup.nick
        v = getattr(obj, k, None)
        if v != None:
            dic[k] = str(v) if v and type(v) not in types else v
    return dic

res_copy_model_to_dest(修改的时候会用到)

def res_copy_model_to_dest(res, dest):
    dic_columns = res.__table__.columns
    # 保证都是字符串和数字
    types = [str, int, float, bool, bytes]
    for k, tmp in dic_columns.items():
        v = getattr(res, k, None)
        value = str(v) if v and type(v) not in types else v
        print("key:", k, "  v:", value)
        if v is not None:
            setattr(dest, k, value)

例:

test = TestModel()
db_test = db.session.query(TestModel).get(test.id)
res_copy_model_to_dest(test, db_test)
db.session.commit()
db.session.close()

在项目中用到的东西,分享一波,有问题可以私信或者评论

作者:筱白爱学习!!

欢迎关注转发评论点赞沟通,您的支持是筱白的动力!

<think>好的,用户让我介绍一下用Python写系统后端。首先,我需要明确用户的需求。可能他们想了解Python在后端开发中的应用,或者想开始学习如何使用Python构建后端系统。用户可能有一定的编程基础,但对后端开发不太熟悉,或者是刚接触Python的人。 首先,我应该概述Python在后端开发中的优势,比如简洁的语法、丰富的框架和库,以及社区支持。然后,需要提到常用的框架,比如Django、Flask、FastAPI,分别说明它们的特点和适用场景,这样用户可以根据项目需求选择合适的工具。 接下来,用户可能需要知道后端开发的基本组成部分,比如路由、视图、数据库交互、RESTful API设计等。需要简要解释这些概念,并说明Python如何处理这些部分,例如使用ORM进行数据库操作,中间件处理请求等。 另外,安全性也是后端开发的重要部分,应该提到常见的措施,如身份验证、授权、数据加密,以及Python框架中提供的安全机制。性能优化可能也是一个关注点,可以谈谈异步处理、缓存策略等。 用户可能还想了解实际的应用案例,比如Web应用、微服务、数据处理平台等,用Python实现的例子,这能帮助他们更好地理解其应用场景。最后,提供一些学习资源或最佳实践,帮助用户进一步学习和实践。 需要确保语言通俗易懂,避免过于专业的术语,或者至少解释清楚术语。同时,结构要清晰,分点说明,让用户容易跟进。可能还需要对比不同框架,帮助用户做出选择。例如,Django适合全功能的大型应用,而Flask更灵活轻量,适合小型项目或微服务。 还要注意用户可能的深层需求,比如他们是否在考虑技术选型,或者正在计划一个项目,需要评估Python是否适合。因此,除了介绍技术点外,还要提到Python在后端开发中的生态和社区支持,这能增强用户的信心。 最后,确保回答全面但不过于冗长,重点突出Python的优势和实际应用,让用户有一个明确的方向去进一步学习或开发。</think>使用 Python 编写系统后端是一种高效且灵活的选择,尤其适合快速开发、高可维护性及扩展性强的项目。以下是关键知识点和常见技术栈的介绍: --- ### **一、Python 后端的优势** 1. **简洁语法**:代码易读易维护,开发效率高。 2. **丰富生态**:成熟的框架和库(如 Django、Flask、FastAPI)。 3. **跨平台**:支持 Linux/Windows/macOS 部署。 4. **异步支持**:通过 `asyncio` 或框架(如 FastAPI)实现高性能并发。 5. **社区活跃**:开源工具多,文档和解决方案丰富。 --- ### **二、核心框架与工具** #### 1. **主流框架** - **Django** - **全栈框架**:内置 ORM、Admin 后台、身份验证等。 - **适用场景**:复杂业务系统(如 CMS、电商后台)。 - **示例代码**: ```python # views.py from django.http import JsonResponse def hello(request): return JsonResponse({"message": "Hello Django!"}) ``` - **Flask** - **轻量灵活**:适合微服务或小型 API。 - **扩展性强**:通过插件(如 Flask-SQLAlchemy)按需添加功能。 - **示例代码**: ```python from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return {"message": "Hello Flask!"} ``` - **FastAPI** - **高性能异步**:基于 ASGI,支持高并发(如实时数据处理)。 - **自动文档**:通过 OpenAPI 生成交互式 API 文档。 - **示例代码**: ```python from fastapi import FastAPI app = FastAPI() @app.get("/") async def hello(): return {"message": "Hello FastAPI!"} ``` #### 2. **数据库交互** - **ORM 工具** - Django ORM(内置)、SQLAlchemy(通用)、Peewee(轻量)。 - **示例(SQLAlchemy)**: ```python from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import declarative_base Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) ``` - **数据库迁移** - 使用 Alembic(搭配 SQLAlchemy)或 Django 内置迁移工具。 #### 3. **API 开发** - **RESTful 设计**:通过框架路由和视图函数定义端点。 - **数据验证**:使用 Pydantic(FastAPI 内置)或 Marshmallow(Flask 插件)。 - **身份验证**:JWT、OAuth2(如 `django-rest-framework-simplejwt`、`authlib`)。 --- ### **三、典型后端架构** ```plaintext 1. 客户端(Web/App) → 2. API 网关 → 3. Python 后端(业务逻辑) → 4. 数据库/缓存 ↘ 5. 消息队列(Celery/RabbitMQ) → 异步任务 ``` --- ### **四、部署与优化** 1. **服务器**:Nginx/Apache 反向代理,Gunicorn/uWSGI 作为应用服务器。 2. **容器化**:Docker + Kubernetes 实现集群部署。 3. **性能优化**: - 缓存:Redis/Memcached。 - 异步任务:Celery 处理耗时操作(如邮件发送)。 - CDN 和静态文件分离。 --- ### **五、应用场景** - **Web 应用**:社交平台、管理系统。 - **微服务**:拆分为独立服务(如用户服务、支付服务)。 - **数据平台**:结合 Pandas/NumPy 进行数据分析。 - **IoT 后台**:处理设备上报数据。 --- ### **六、学习资源** 1. 官方文档:Django、Flask、FastAPI。 2. 实战项目:从 Todo List 开始,逐步构建博客、电商系统。 3. 工具链:Postman(API 测试)、Swagger(文档生成)。 --- 通过 Python 开发系统后端,开发者可以快速实现从原型到生产的全流程,特别适合敏捷开发和中小型项目。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱白爱学习

你的鼓励将是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值