• 【tips】ORM


    优先(官方文档SQLAlchemy-version1.2): sqlalchemy | 作者:斯芬克斯
    推荐一(长篇幅version1.2.0b3):python约会之ORM—sqlalchemy | 作者:大牧莫邪
    推荐二(短篇幅): 使用SQLAlchemy | 作者:廖雪峰
    参考(长篇幅): Python中操作SQLAlchemy | 作者:俊采星驰_87e0

    备注:本篇文章基于python3环境下使用sqlalchemy。

    ORM介绍(作用:不用原生SQL语句对数据库操作)

    一、什么是orm(orm是一种术语而不是软件)

    1)orm英文全称object relational mapping,就是对象映射关系程序
    2)简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的
    3)为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系
    4)这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言

    总结:类似把C盘深层次文件或文件夹拉到桌面,本质也是映射磁盘位置信息,其实也与快捷方式图标启动应用程序也有异曲同工之妙。ORM就是用面向对象的方式操作mysql数据库。

    二、ORM作用

    1)隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
    2)ORM使我们构造固化数据结构变得简单易行。

    三、ORM缺点

    1)无可避免的,自动化意味着映射和关联管理,代价是牺牲性能
    2)现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。


    目录

    1. SQLAlchemy基础操作
      1.1 安装
      1.2 连接引擎
      1.3 连接会话
    2. ORM之Object操作
      2.1 基础类
      2.2 数据类型创建
      2.3 数据类型映射操作
      2.4 增加和更新
    3. SQLAlchemy核心操作(数据的查询)
      3.1 查询对象Query
          3.1.1 常规查询query
          3.1.2 指定排序查询
          3.1.3 指定列查询
          3.1.4 指定列属性别名
          3.1.5 指定类型别名
          3.1.6 切片查询
      3.2 条件筛选filter
          3.2.1 等值条件 — equals / not equals
          3.2.2 模糊条件 — like
          3.2.3 范围条件 — in / not in
          3.2.4 空值条件 — is null / is not null
          3.2.5 并且条件 — AND
          3.2.6 或者条件 — OR
          3.2.7 SQL语句查询
      3.3. 查询结果
          3.3.1 all()函数返回查询列表
          3.3.2 filter()函数返回单项数据的列表生成器
          3.3.3 one()/one_or_none()/scalar()返回单独的一个数据对象

    1.1 安装

    首先确保你的PC已经具备了完善的python3开发环境
    安装sqlalchemy,执行如下命令使用pip安装即可(推荐)

    $ pip3 install sqlalchemy
    

    或者执行如下命令通过easy_install进行安装(亲测:python3环境下使用以下命令安装偶尔会出现模块引入不到的问题)

    $ easy_install sqlalchemy
    

    安装完成之后,可以通过引入sqlalchemy进行版本查看,确认sqlalchemy安装成功

    >>> import sqlalchemy
    >>> sqlalchemy.__version__
    '1.2.14'
    
    

    1.2 连接引擎

    使用sqlalchemy进行数据库操作,首先我们需要建立一个指定数据库的连接引擎对象
    建立引擎对象的方式被封装在了sqlalchemy.create_engine函数中,通过指定的数据库连接信息就可以进行创建

    创建数据库连接引擎时参数设置语法:

    # 语法规则:dialect[+driver]://user:password@host/dbname[?key=value..]
    # 引入建立引擎的模块
    from sqlalchemy import create_engine
    # 创建一个和mysql数据库之间的连接引擎对象
    engine = create_engine("mysql://root:root@localhost/py1709", 
    encoding="utf-8", echo=True)
    
    

    指定的数据库连接字符串表示了目标数据库的配置信息;encoding配置参数指定了和和数据库之间交换的数据的编码方式,同时echo参数表示随时在控制台展示和数据库之间交互的各种信息
    create_engine()函数返回的是sqlalchemy最核心的接口之一,该引擎对象会根据开发人员指定的数据库进行对应的sql api的调用处理
    连接postgresql数据库:
    engine = create_engine("postgresql://scott:tiger@localhost/test")
    连接mysql数据库:
    engine = create_engine("mysql://scott:tiger@hostname/dbname",
    encoding='utf-8', echo=True)
    其他连接方式请参考官方文档:http://docs.sqlalchemy.org/en/latest/

    1.3 连接会话

    创建了数据库连接引擎对象之后,我们需要获取和指定数据库之间的连接,通过连接进行数据库中数据的增删改查操作,和数据库的连接我们称之为和指定数据库之间的会话,通过指定的一个模块

    sqlalchemy.sessionmaker进行创建
    # 引入创建session连接会话需要的处理模块
    from sqlalchemy.orm import sessionmaker
    # 创建一个连接会话对象;需要指定是和那个数据库引擎之间的会话
    Session = sessionmaker(bind=engine)
    session = Session()
    # 接下来~就可以用过session会话进行数据库的数据操作了。
    
    

    PS:如果在创建会话的时候还没有指定数据库引擎,可以通过如下的方式完成会话操作

    Session = sessionmaker()
    ..
    Session.configure(bind=engine)
    session = Session()
    ..
    
    

    2. ORM之Object操作

    我们的程序中的对象要使用sqlalchemy的管理,实现对象的orm操作,就需要按照框架指定的方式进行类型的创建操作,sqlalchemy封装了基础类的声明操作和字段属性的定义限制方式,开发人员要做的事情就是引入需要的模块并在创建对象的时候使用它们即可

    基础类封装在sqlalchemy.ext.declarative.declarative_base模块中
    字段属性的定义封装在sqlalchemy模块中,通过sqlalchemy.Column定义属性,通过封装的Integer、String、Float等定义属性的限制

    2.1 基础类

    创建基础类的方式如下:

    # 引入需要的模块
    from sqlalchemy.ext.declarative import declarative_base
    
    # 创建基础类
    BaseModel = declarative_base()
    
    
    2.2 数据类型创建

    创建数据模型的操作

    # 引入需要的模块
    from sqlalchemy import Column, String, Integer
    
    # 创建用户类型
    class User(BaseModel):
        # 定义和指定数据库表之间的关联
        __tabelname__ = “user”
        # 创建字段类型
        id = Column(Integer, primary_key=True)
        name = Column(String(50))
        age = Column(Integer)
    
    

    PS:定义的数据类型必须继承自之前创建的BaseModel,同时通过指定tablename确定和数据库中某个数据表之间的关联关系,指定某列类型为primary_key设定的主键,其他就是通过Column指定的自定义属性了。
    sqlalchemy会根据指定的tablename和对应的Column列字段构建自己的accessors访问器对象,这个过程可以成为instrumentation,经过instrumentation映射的类型既可以进行数据库中数据的操作了。

    2.3 数据类型映射操作

    完成了类的声明定义之后,Declarative会通过python的metaclass对当前类型进行操作,根据定义的数据类型创建table对象,构建程序中类型和数据库table对象之间的映射mapping关系

    通过类型对象的metadata可以实现和数据库之间的交互,有需要时可以通过metadata发起create table操作,通过Base.metadata.create_all()进行操作,该操作会检查目标数据库中是否有需要创建的表,不存在的情况下创建对应的表

    ..
    
    if __name__ == “__main__”:
    Base.metadata.create_all(engine)
    ..
    
    
    2.4 增加和更新

    下面就是核心的数据对象的处理了,在程序代码中根据定义的数据类型创建对象的方式比较简单,执行如下的操作创建一个对象:

    $ user = User(name=”tom”, age=18)
    $ print(user.name)
    tom
    $ print(user.id)
    None
    
    

    通过会话对象将对象数据持久化到数据库的操作

    $ session.add(user)
    $ print(user.id)
    None
    $ session.commit()
    $ print(user.id)
    1
    
    

    3.1 查询对象Query

    Session是sqlalchemy和数据库交互的桥梁,Session提供了一个Query对象实现数据库中数据的查询操作

    3.1.1 常规查询query

    直接指定类型进行查询

    user_list = session.query(User)
    for user in user_list:
        print(user.name)
    
    
    3.1.2 指定排序查询

    通过类型的属性指定排序方式

    user_list = session.query(User).order_by(User.id) # 默认顺序
    user_list = session.query(User).order_by(-User.id) # 指定倒序
    user_list = session.query(User).order_by(-User.id, User.name) # 多个字段
    
    
    3.1.3 指定列查询

    指定查询数据对象的属性,查询目标数据

    user_list = session.query(User, User.name).all()
    for u in user_list:
        print(u.User, u.name)
    
    
    3.1.4 指定列属性别名

    对于名称较长的字段属性,可以指定名称在使用时简化操作

    user_list = session.query(Usre.name.label(‘n’)).all()
    
    for user in user_list:
        print(user.n)
    
    
    3.1.5 指定类型别名

    对于类型名称较长的情况,同样可以指定别名进行处理

    from sqlalchemy.orm import aliased
    
    user_alias = aliased(User, name=’u_alias’)
    
    user_list = session.query(u_alias, u_alias.name).all()
    for u in user_list:
        print(u.u_alias, u.name)
    
    
    3.1.6 切片查询

    对于经常用于分页操作的切片查询,在使用过程中直接使用python内置的切片即可

    user_list = session.query(User).all()[1:3]
    ..
    
    

    3.2 条件筛选filter

    前一节中主要是对于数据查询对象query有一个比较直观的感受和操作,在实际使用过程中经常用到条件查询,主要通过filter和filter_by进行操作,重点讲解使用最为频繁的filter条件筛选函数

    3.2.1 等值条件——equals / not equals
    # equals
    session.query(User).filter(User.id == 1) # 相等判断
    # not equals
    session.query(User).filter(User.name != ‘tom’)# 不等判断
    
    
    3.2.2 模糊条件——like
    session.query(User).filter(User.name.like(‘%tom%’))
    
    
    3.2.3 范围条件——in / not in
    # IN
    session.query(User).filter(User.id.in_([1,2,3,4]))
    
    session.query(User).filter(User.name.in_([
         session.query(User.name).filter(User.id.in_[1,2,3,4])
    ]))
    
    # NOT IN
    session.query(User).filter(~User.id.in_([1,2,3]))
    
    
    3.2.4 空值条件——is null / is not null
    # IS NULL
    session.query(User).filter(User.name == None)
    session.query(User).filter(User.name.is_(None)) # pep8
    
    # IS NOT NULL
    session.query(User).filter(User.name != None)
    session.query(User).filter(User.name.isnot(None)) # pep8
    
    
    3.2.5 并且条件——AND
    from sqlalchemy import and_
    
    session.query(User).filter(User.name=’tom’).filter(User.age=12)
    session.query(User).filter(User.name=’tom’, User.age=12)
    session.query(User).filter(and_(User.name=’tom’, User.age=12))
    
    
    3.2.6 或者条件——OR
    from sqlalchemy import or_
    session.query(User).filter(or_(User.name=’tom’, User.name=’jerry’))
    
    
    3.2.7 SQL语句查询

    某些特殊情况下,我们也可能在自己的程序中直接使用sql语句进行操作

    from sqlalchemy import text
    session.query(User).from_statement(
    text(‘select * from users where name=:name and age=:age’))
    .params(name=’tom’, age=12).all()
    
    

    3.3 查询结果

    3.3.1 all()函数返回查询列表
    session.query(User).all()
    [..]
    
    
    3.3.2 filter()函数返回单项数据的列表生成器
    session.query(User).filter(..)
    <..>
    
    
    3.3.3 one()/one_or_none()/scalar()返回单独的一个数据对象
    session.query(User).filter(..).one()/one_or_none()/scalar()
    ..
    
    
  • 相关阅读:
    Lightoj 1422
    BZOJ 1801 [AHOI 2009] 中国象棋(DP)
    [SCOI2008]天平
    [SCOI2008]奖励关
    [USACO08JAN]haybale猜测Haybale Guessing
    [Sdoi2016]征途
    [SHOI2014]概率充电器
    [USACO08JAN]电话线Telephone Lines
    [HEOI2016]排序
    友好的生物
  • 原文地址:https://www.cnblogs.com/wqunlong/p/10048846.html
Copyright © 2020-2023  润新知