第17次课

python中使用SQLAlchemy

概念简介

  • ORM
    ORM是Object-Relational Mapping的简写。今天学习的SQLAlchemy其实就是ORM框架中最有名的一个。
    SQLAlchemy框架工做
    经过数据的API,使用关系对象映射进行数据库操做,也就是:将对象转换成SQL,而后使用数据API执行SQL并获取执行结果。orm-sqlalchemy-coreorm-sqlalchemy-core
    SQLAlchemy自己没法操做数据库,其必须经过pymysql等第三方插件。上图中Dialect用于和数据API进行交流,根据配置文件的不一样调用不一样的数据库API,从而实现对数据库的操做。
    1
    2
    3
    4
    5
    6
    7
    8
    # mysqldb
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
    # pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
    # mysql-connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
    # cx_oracle
     oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]

对比

ORM思想的核心是隐藏了数据访问细节,提供了通用的数据库交互。而且彻底不用考虑SQL语句,从而快速开发。html

  • 使用SQL建立表
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE student(
      id int not null auto_increment,
      name varchar(100),
      age int,
      address varchar(100),
      PRIMARY KEY(id)
    )

上述是一个简单的建立单表的语句。python

  • 使用SQLAlchemy
    方法1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from sqlalchemy import create_engine, Column, String, Integer, MetaData
    from sqlalchemy.ext.declarative import declarative_base
    
    engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
    
    Base = declarative_base()    #生成orm基类
    
    class Student(Base):
        __tablename__ = 'student'    #指定表名
        id = Column(Integer, primary_key=True)
        name = Column(String(100))
        age = Column(Integer)
        address = Column(String(100))
    
    Base.metadata.create_all(engine)    #建立表结构

方法2mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from sqlalchemy import Table, MetaData, Column, Integer, String, create_engine
from sqlalchemy.orm import mapper

engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
metadata = MetaData()

student = Table('student', metadata,
             Column('id', Integer, primary_key=True),
             Column('name', String(100)),
             Column('age', Integer),
             Column('address', String(100))
             )


class Student(object):
    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address


mapper(Student, student)    #此处有问题,待解决

 

说明
echo=True 显示每条执行的SQL语句,能够关闭。
create_engine()返回一个Engine的实例,而且表示经过数据库语法处理细节的核心接口,这种状况下数据库语法将被解释成python的类方法。
上面简单示例对比了下使用SQL直接建立表和使用ORM框架建表的区别,下面开始介绍SQLAlchemy的使用。sql

使用

安装

经过pip install SQLAlchemy安装,访问mysql使用pymysql,安装方法pip install pumysql。能够参照python访问mysql数据库

插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from sqlalchemy import create_engine, Column, String, Integer, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:123456@localhost/test", encoding='UTF-8', echo=True)
DBsession = sessionmaker(bind=engine) #建立与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
session = DBsession()    #生成session实例
Base = declarative_base()

class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    age = Column(Integer)
    address = Column(String(100))


student1 = Student(id=1001, name='Alice', age=25, address="anhui")
student2 = Student(id=1002, name='Bob', age=69, address="beijing")
student3 = Student(id=1003, name='Cerry', age=14, address="jiangsu")

session.add_all([student1, student2, student3])
session.commit()
session.close()

查询

查询是经过Session的query()方法建立一个查询对象,这个函数的参数能够是任何类或者类的描述的集合。
查询出来的数据是一个对象,直接经过对象的属性调用。数组

1
2
3
4
5
6
7
8
9
10
11
12
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from db.orm2 import Student

engine = create_engine('mysql+pymysql://root:123456@localhost/test')
DBsession = sessionmaker(bind=engine)
session = DBsession()

a = session.query(Student)
print(a)
for i in a:
    print(i.id, i.name, i.age, i.address)

 

输出结果session

1
2
3
4
5
SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age, student.address AS student_address 
FROM student
1001 Alice 25 anhui
1002 Bob 69 beijing
1003 Cerry 14 jiangsu

 

session.query(Student)结果为查询的SQL语句,若出现查询结果错误能够经过查看SQL确认。oracle

  • filter()和filter_by()
    过滤条件。==!=like等过滤操做均可以在filter函数中使用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from db.orm2 import Student
    
    engine = create_engine('mysql+pymysql://root:123456@localhost/test')
    DBsession = sessionmaker(bind=engine)
    session = DBsession()
    
    a = session.query(Student).filter(Student.id == 1001)
    b = session.query(Student).filter_by(id=1001)
    
    for x in a:
        print(x.id, x.name, x.age, x.address)
    for i in b:
        print(i.id, i.name, i.age, i.address)

输出结果app

1
2
1001 Alice 25 anhui
1001 Alice 25 anhui

 

filter()filter_by()区别
filter能够像写sql的where条件那样写>、<等条件,但引用列名时,须要经过类名.属性名的方式。
filter_by能够使用python的正常参数传递方法传递条件,指定列名时,不须要额外指定类名,参数名对应类中的属性名,不能使用>、<等条件。
当使用filter的时候条件之间是使用==,filter_by使用的是=
filter不支持组合查询,只能连续调用filter变相实现。filter_by的参数是**kwargs,直接支持组合查询。框架

1
2
3
4
filters = {'id':1002, 'name':'Bob'}
b = session.query(Student).filter_by(**filters)
for i in b:
    print(i.id, i.name, i.age, i.address)

 

输出结果

1
1002 Bob 69 beijing

 

  • all()
    返回一个列表,能够经过遍历列表获取每一个对象。
    1
    2
    3
    4
    a = session.query(Student).filter(Student.id > 1001).all()
    print(a)
    for x in a:
        print(x.id, x.name, x.age, x.address)

输出结果

1
2
3
[<db.orm2.Student object at 0x00000197ECC759E8>, <db.orm2.Student object at 0x00000197ECC75A58>]
1002 Bob 69 beijing
1003 Cerry 14 jiangsu

 

  • one()
    返回且仅返回一个查询结果。当结果数量不足或者多于一个时会报错。
    1
    2
    3
    a = session.query(Student).filter(Student.id == 1001).one()
    print(a)
    print(a.id, a.name, a.age, a.address)

输出结果

1
2
<db.orm2.Student object at 0x000001B7C57E7908>
1001 Alice 25 anhui

 

  • first()
    返回至多一个结果,并且以单项形式,而不是只有一个元素的tuple形式返回。
    1
    2
    3
    a = session.query(Student).filter(Student.id > 1001).first()
    print(a)
    print(a.id, a.name, a.age, a.address)

输出结果

1
2
<db.orm2.Student object at 0x000001C63E536B00>
1002 Bob 69 beijing

 

说明

  1. MetaData类
    主要用于保存表结构,链接字符串等数据,是一个多表共享的对象。
    metadata = MetaData(engine)绑定一个数据源的metadata。
    metadata.create_all(engine) 建立表,该操做会先判断表是否存在,若存在则不建立。
  2. Table类
    构造函数为Table.__init__(self, name, metadata,*args, **kwargs)
    name 表名
    metadata 共享的元数据
    args中Column是列定义
    下面是可变参数`*
    kwargs`定义
    schema 此表的结构名称,默认None
    autoload 自动从现有表中读入表结构,默认False
    autoload_with 从其余engine读取结构,默认None
    include_columns 若是autoload设置为True,则此项数组中的列明将被引用,没有写的列明将被忽略,None表示全部都列明都引用,默认None
    mustexist 若是为True,表示这个表必须在其余的python应用中定义,必须是metadata的一部分,默认False
    useexisting 若是为True,表示这个表必须被其余应用定义过,将忽略结构定义,默认False
    owner 表全部者,用于Orcal,默认None
    quote 设置为True,若是代表是SQL关键字,将强制转义,默认False
    quote_schema 设置为True,若是列明是SQL关键字,将强制转义,默认False
    mysql_engine mysql专用,能够设置’InnoDB’或’MyISAM’
  3. Column类
    构造函数为Column.__init__(self, name, type_, *args, **kwargs)
    name 列名
    type_ 类型,更多类型sqlalchemy.types
    下面是*args参数定义
    Constraint(约束)
    ForeignKey(外键)
    ColumnDefault(默认)
    Sequenceobjects(序列)定义
    key 列名的别名,默认None
    下面是**kwargs参数定义
    primary_key 若是为True,则是主键
    nullable 是否可为Null,默认是True
    default 默认值,默认是None
    index 是不是索引,默认是True
    unique 是否惟一键,默认是False
    onupdate 指定一个更新时候的值,这个操做是定义在SQLAlchemy中,不是在数据库里的,当更新一条数据时设置,大部分用于updateTime这类字段
    autoincrement 设置为整型自动增加,只有没有默认值,而且是Integer类型,默认是True
    quote 若是列明是关键字,则强制转义,默认False
  4. 建立会话
    Session的主要目的是创建与数据库的会话,它维护你加载和关联的全部数据库对象。它是数据库查询(Query)的一个入口。
    SQLAlchemy中,数据库的查询操做是经过Query对象来实现的,而Session提供了建立Query对象的接口。Query对象返回的结果是一组同一映射(Identity Map)对象组成的集合。事实上,集合中的一个对象,对应于数据库表中的一行(即一条记录)。所谓同一映射,是指每一个对象有一个惟一的ID。若是两个对象(的引用)ID相同,则认为它们对应的是相同的对象。
    要完成数据库查询,就须要创建与数据库的链接。这就须要用到Engine对象。一个Engine多是关联一个Session对象,也可能关联一个数据库表。
    固然Session最重要的功能仍是实现原子操做。
    ORM经过session与数据库创建链接进行通讯,以下所示
    1
    2
    3
    4
    from sqlalchemy.orm import sessionmaker
    
    DBSession = sessionmaker(bind=engine)
    session = DBSession()

经过sessionmake方法建立一个Session工厂,而后在调用工厂的方法来实例化一个Session对象。

要了解更多关于SQLAlchemy内容能够点击SQLAlchemy Documentation查看官方介绍。

分享

相关文章
相关标签/搜索