python ORM技术

1.ORM技术简介

ORM:Object-Relational Mapping,把关系数据库的表结构映射到对象上。

数据库表是一个二维表,包含多行多列。把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user表

[
    ('1', 'Michael'),
    ('2', 'Bob'),
    ('3', 'Adam')
]
Python的DB-API返回的数据结构就是像上面这样表示的, 但是用tuple表示一行很难看出表的结构。如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来:
class User(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

[
    User('1', 'Michael'),
    User('2', 'Bob'),
    User('3', 'Adam')
]

2.SQLAlchemy的使用

上述就是ORM技术 ,把关系数据库的表结构映射到对象上。但是由谁来做这个转换呢?所以ORM框架应运而生。  在Python中,最有名的ORM框架是SQLAlchemy。我们来看看SQLAlchemy的用法。  首先通过pip安装SQLAlchemy:

$ pip install sqlalchemy

初始化连接:

$ from sqlalchemy import create_engine #导入$ engine = create_engine('mysql+pymsql://user:passwd@serverip/dbname', echo=True)
echo参数为True时,会显示每条执行的SQL语句,可以不写即为关闭。
create_engine()返回一个Engine的实例,并且它表示通过数据库语法处理细节的核心接口,在这种情况下,数据库语法将会被解释成python的类方法。
mysql:  指定是哪种数据库连接,+pymsql 使用该包进行连接,默认为mysqldb。
user: 连接的用户名
passwd:连接用户对应的密码
serverIP: 数据库的ip
dbname: 需要连接库的名字
1).创建数据表

(1)主要是通过sql语句来创建表格:

from sqlalchemy import create_engine # 导入:

engine = create_engine('mysql+pymysql://xiang:[email protected]/sqlalchemy') #创建连接

#建表语句
sql = '''create table student(   
  id int not null PRIMARY KEY,
  name varchar(100),
  age int,
  address varchar(100)
);'''

cus = engine.connect() #获取连接
cus.execute(sql) #创建
cus.close()      #关闭
engine.connect() 表示获取到数据库连接。类似我们在pymysql中游标course的作用。


(2)通过ORM的方式创建表

# 导入from sqlalchemy import create_engine, MetaData, Column, Integer, String, Table

# 初始化数据库连接(echo=True打印操作信息):
engine = create_engine("mysql+pymysql://user:passwd@IP/test")

# 创建users表
metadata = MetaData(engine)
users = Table('users',metadata,
        Column('id',Integer,primary_key=True),
        Column('name',String(10)),
        Column('password',Integer),
        Column('email',Integer,unique=True),
        Column('score',Integer)
             )
#如果要创建多个表继续写就行了#user2 = Table('user2',metadata,
        Column(...)
             ) # 创建表
metadata.create_all(engine)

运行之后users表就创建好了:

mysql> desc users;
+----------+-------------+------+-----+---------+----------------+
| Field        | Type             | Null  | Key  | Default  | Extra                |
+----------+-------------+------+-----+---------+----------------+
| id             | int(11)         | NO   | PRI   | NULL     | auto_increment |
| name       | varchar(10) | YES   |         | NULL     |                          |
| password | int(11)         | YES  |         | NULL     |                          |
| email        | int(11)         | YES  | UNI | NULL      |                         |
| score        | int(11)         | YES  |         | NULL     |                         |
+----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

MetaData类主要用于保存表结构,连接字符串等数据,是一个多表共享的对象

metadata = MetaData(engine)    绑定一个数据源的metadata
metadata.create_all(engine)      是来创建表,这个操作是安全的操作,会先判断表是否存在。

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'

Column类 构造函数:

Column.__init__(self,  name,  type_,  *args,  **kwargs)
1、name 列名
2、type_ 类型,更多类型 sqlalchemy.types
3、*args Constraint(约束),  ForeignKey(外键),  ColumnDefault(默认), Sequenceobjects(序列)定义
4、key 列名的别名,默认None
下面是可变参数 **kwargs
5、primary_key 如果为True,则是主键
6、nullable 是否可为Null,默认是True
7、default 默认值,默认是None
8、index 是否是索引,默认是True
9、unique 是否唯一键,默认是False
10、onupdate 指定一个更新时候的值,这个操作是定义在SQLAlchemy中,不是在数据库里的,当更新一条数据时设置,大部分用于updateTime这类字段
11、autoincrement 设置为整型自动增长,只有没有默认值,并且是Integer类型,默认是True
12、quote 如果列明是关键字,则强制转义,默认False
2.创建会话,并对数据进行增删改查操作

说到数据库,就离不开Session。Session的主要目的是建立与数据库的会话,它维护你加载和关联的所有数据库对象。它是数据库查询(Query)的一个入口。

在Sqlalchemy中,数据库的查询操作是通过Query对象来实现的。而Session提供了创建Query对象的接口。
Query对象返回的结果是一组同一映射(Identity Map)对象组成的集合。事实上,集合中的一个对象,对应于数据库表中的一行(即一条记录)。所谓同一映射,是指每个对象有一个唯一的ID。如果两个对象(的引用)ID相同,则认为它们对应的是相同的对象。
要完成数据库查询,就需要建立与数据库的连接。这就需要用到Engine对象。一个Engine可能是关联一个Session对象,也可能关联一个数据库表。
当然Session最重要的功能还是实现原子操作。

ORM通过session与数据库建立连接进行通信,如下所示:

# 导入:
from sqlalchemy.orm import sessionmaker
DBSession = sessionmaker(bind=engine)
session = DBSession()
通过sessionmake方法创建一个Session工厂,然后在调用工厂的方法来实例化一个Session对象。
增加数据

# 导入
from sqlalchemy import create_engine, MetaData, Column, Integer, String, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 初始化数据库连接
engine = create_engine("mysql+pymysql://user:passwd@IP/test")

# 创建DBSession类型:
DBsession = sessionmaker(bind=engine)
session = DBsession()

# 创建对象的基类:
Base = declarative_base()

class User(Base):
    # 表的名字:
    __tablename__ = 'users'

    # 表的结构:
    id = Column(Integer(), primary_key=True)
    name = Column(String(10))
    password=Column(Integer())
    email=Column(Integer(),unique=True)
    score=Column(Integer())

# 添加数据
u1=User(name='a',password=1,email=1,score=12)
u2=User(name='b',password=2,email=2,score=15)
u3=User(name='c',password=3,email=3,score=21)
session.add_all([u1,u2,u3])
session.commit()
session.close()

这样数据就添加上了:

mysql> select * from users;
+----+------+----------+-------+-------+
| id    | name | password | email | score |
+----+------+----------+-------+-------+
|  1     | a      |             1 |         1 |        12 |
|  2     | b      |             2 |         2 |        15 |
|  3     | c      |             3 |         3 |        21 |
+----+------+----------+-------+-------+
3 rows in set (0.00 sec)

查询数据

filter(User.id==1001)  这个就必须使用User.id ,可以使用> < ==等

#查询数据
user=session.query(User).filter(User.id==1).one()
print('type:',type(user))
print('name:',user.name)

将添加例子中的添加数据操作替换为查询即可,运行结果:

type: <class '__main__.User'>
name: a

可见,ORM就是把数据库表的行与相应的对象建立关联,互相转换。

上述的命令中one()表示一个,也可是使用all()表示多个:

user=session.query(User).filter(User.id>1).all()
print(user)
for i in user:
    print(i.id,i.name)

运行结果为:

[<__main__.User object at 0x0000029AB569A2B0>, <__main__.User object at 0x0000029AB569A320>]
2 b
3 c

filter_by(id=1)  不能使用>  <  ==

user=session.query(User).filter_by(id=1).one()
print(user.id,user.name)

运行结果为:

1 a


修改数据

#修改数据:获取一条数据对象,修改属性并提交即可
user=session.query(User).filter(User.id==1).one()
user.score=99
session.commit()
session.close()

我们查一下看是否改变:

mysql> select * from users;
+----+------+----------+-------+-------+
| id     | name | password | email | score |
+----+------+----------+-------+-------+
|  1    | a        |            1 |         1 |        99 |
|  2    | b        |            2 |         2 |        15 |
|  3    | c        |            3 |         3 |        21 |
+----+------+----------+-------+-------+
3 rows in set (0.00 sec)

可见已经改变。

删除数据

#删除用户
u=session.query(User).filter(User.id==2).one()
session.delete(u)
session.commit()

提交查看结果:

mysql> select * from users;
+----+------+----------+-------+-------+
|     id | name | password | email | score |
+----+------+----------+-------+-------+
|  1     | a        |            1 |         1 |        99 |
|  3     | c        |            3 |         3 |        21 |
+----+------+----------+-------+-------+

2 rows in set (0.00 sec)


可见id为2的数据已经没有了。

猜你喜欢

转载自blog.csdn.net/weixin_39318540/article/details/80278221