Python orm基础
ORM 对象映射关系程序。
通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。
orm的优点:
- 隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
- ORM使我们构造固化数据结构变得简单易行。
缺点:
- 无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。
最有名的ORM框架是SQLAlchemy,系统中没有该模块的需要安装 pip install sqlalchemy (或easy_install SQLAlchemy)
如果在pip install sqlalchemy 中报ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org'错,需要先设置超时时间:pip --default-timeout=100 install -U Pillow,再重新安装 pip install sqlalchemy,通过imort sqlalchemy验证是否安装正常。
ORM框架SQLAlchemy 使用,创建表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#conding:utf-8 import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String #区分大小写 #创建连接 engine = create_engine( "mysql+pymysql://root:123456@localhost/ceshi" ,encoding = 'utf-8' ,echo = True ) #生成orm基类 base = declarative_base() class user(base): __tablename__ = 'users' #表名 id = Column(Integer, primary_key = True ) name = Column(String( 32 )) password = Column(String( 64 )) base.metadata.create_all(engine) #创建表结构 |
注:pymysql设置编码字符集一定要在数据库访问的URL上增加?charset=utf8,否则数据库的连接就不是utf8的编码格式
1
|
engine = create_engine( "mysql+pymysql://root:123456@localhost/ceshi" ,encoding = 'utf-8' ,echo = True ) |
ORM框架SQLAlchemy 使用,插入数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#conding:utf-8 import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String #区分大小写 from sqlalchemy.orm import sessionmaker #创建连接 engine = create_engine( "mysql+pymysql://root:123456@localhost/ceshi" ,encoding = 'utf-8' ,echo = True ) #生成orm基类 base = declarative_base() class user(base): __tablename__ = 'users' #表名 id = Column(Integer, primary_key = True ) name = Column(String( 32 )) password = Column(String( 64 )) base.metadata.create_all(engine) #创建表结构 Session_class = sessionmaker(bind = engine) ##创建与数据库的会话,class,不是实例 Session = Session_class() #生成session实例 user_obj = user(name = "rr" ,password = "123456" ) #插入你要创建的数据对象,每执行一次都会新增一次数据。 print user_obj.name,user_obj. id #此时还没创建对象呢,不信你打印一下id发现还是None Session.add(user_obj) #把要创建的数据对象添加到这个session里 print user_obj.name,user_obj. id #此时也依然还没创建 Session.commit() #提交,使前面修改的数据生效。 |
结果:
查询:
1
2
3
|
my_user = Session.query(user).filter_by(name = "ee" ).first() #创建查询对象 print (my_user. id ,my_user.name,my_user.password) #输出查询内容 print my_user #内存地址 |
结果:
修改:
1
2
3
|
my_user = Session.query(user).filter_by(name = "yy" ).first() #根据指定条件创建符合条件的对象 my_user.name = 'uu' #将name='yy'的name修改为uu print (my_user. id ,my_user.name,my_user.password) #输出查询内容 |
结果:
参考数据表:
回滚:
1
2
3
4
5
6
7
|
user_obj = user(name = "kk" ,password = "99999" ) #插入你要创建的数据对象 Session.add(user_obj) #把要创建的数据对象添加到这个session里 my_user = Session.query(user).filter_by(name = "rr" ).first() #根据指定条件创建符合条件的对象,first()是指name='rr'的第一条记录 my_user.name = "gg" #将name='yy'的name修改为uu print (Session.query(user). filter (user.name.in_([ "gg" , "kk" ])). all ()) #显示修改后的数据 Session.rollback() #回滚 print (Session.query(user). filter (user.name.in_([ "gg" , "kk" ])). all ()) #显示回滚后的内容 |
结果:
获取所有数据
1
|
print Session.query(user. id ,user.name). all () #只显示id,name |
结果:
多条件查询
1
2
|
objs = Session.query(user). filter (user. id > 0 ). filter (user. id < = 3 ). all () #注意:filter()中的关键字不能是表达式user.id=0 print objs |
filter的关系相当于 user.id >0 AND user.id <=3 的效果
结果:
统计和分组
1
2
|
objs = Session.query(user). filter (user.name.like( 'r%' )).count() #统计 print objs |
结果:
1
2
|
from sqlalchemy import func print (Session.query(func.count(user.name),user.name).group_by(user.name). all () ) #分组 |
结果:
外键关联
参照表:两张表是一对多的关系。
1
|
users(一) |
addresses(多)
创建表addresses,将users表中的id作为addresses表的外键。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,ForeignKey #区分大小写 from sqlalchemy.orm import sessionmaker,relationship #创建连接 engine = create_engine( "mysql+pymysql://root:123456@localhost/ceshi" ,encoding = 'utf-8' ,echo = True ) #生成orm基类 base = declarative_base() class user(base): __tablename__ = 'users' #表名 id = Column(Integer, primary_key = True ) name = Column(String( 32 )) password = Column(String( 64 )) def __repr__( self ): return "<user(id='%d',name='%s', password='%s')>" % ( self . id , self .name, self .password) class Address(base): __tablename__ = 'addresses' id = Column(Integer, primary_key = True ) email_address = Column(String( 32 ), nullable = False ) user_id = Column(Integer, ForeignKey( 'users.id' )) user = relationship( "user" , backref = "addresses" ) '''允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项,在内存中创建。在addresses表中可以使用user来查询users表中的数据,在users表中可以使用backref后的addresses来查询assresses表中的数据。''' def __repr__( self ): return "<Address(email_address='%s',id='%d',user_id='%d')>" % ( self .email_address, self . id , self .user_id) base.metadata.create_all(engine) #创建表结构 Session_class = sessionmaker(bind = engine) #创建与数据库的会话,class,不是实例 Session = Session_class() #生成session实例 obj = Session.query(user).first() print obj.addresses #在users表里面通过addresses来查询addresses表中的数据。 for i in obj.addresses: print i addr_obj = Session.query(Address).first() print (addr_obj.user) #在addresses表中通过user来查询users表中的数据。 print (addr_obj.user.name) Session.commit() #提交,使前面修改的数据生效。 |
结果:
输出的结果1是列表形式,print 多行记录时以列表的形式显示。
注:在定义表的类下面加 def
__repr__(
self
):
return ... 是为了在print时输出哪些数据,以及输出后的显示形式。
补充:1.主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性
2.外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定是至少涉及到两张表。例如下面这两张表:
设定条件向指定表中添加记录:
1
2
3
4
5
|
obj = Session.query(user). filter (user.name = = 'ee' ). all ()[ 0 ] #设定条件 print (obj.addresses) obj.addresses = [Address(email_address = "ertttt" ), #向addresses表中添加2列。 Address(email_address = "dddd" )] |
结果:
多外键关联
在Customer表有2个字段都关联了Address表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Customer(base): __tablename__ = 'customer' id = Column(Integer, primary_key = True ) name = Column(String) billing_address_id = Column(Integer, ForeignKey( "address.id" )) shipping_address_id = Column(Integer, ForeignKey( "address.id" )) '''#创建的列billing_address_id、shipping_address_id都作为外键关联address表中id列''' billing_address = relationship( "Address" ) shipping_address = relationship( "Address" ) #创建两个关联项 class Address(base): __tablename__ = 'address' id = Column(Integer, primary_key = True ) street = Column(String) city = Column(String) state = Column(String) |
如果报错:
sqlalchemy.exc.AmbiguousForeignKeysError: Could
not
determine join
condition between parent
/
child tables on relationship
Customer.billing_address
-
there are multiple foreign key
1
2
|
illing_address = relationship( "Address" , foreign_keys = [billing_address_id]) shipping_address = relationship( "Address" , foreign_keys = [shipping_address_id]) |
使pymysql分清哪个外键是对应哪个字段。
多对多关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine( "mysql+pymysql://root:123456@localhost/ceshi" ,encoding = 'utf-8' ,echo = True ) base = declarative_base() book_m2m_author = Table( 'book_m2m_author' , base.metadata, Column( 'book_id' ,Integer,ForeignKey( 'books.id' )), Column( 'author_id' ,Integer,ForeignKey( 'authors.id' )), ) #创建book_m2m_author表,关联另外两张表。 class Book(base): __tablename__ = 'books' id = Column(Integer,primary_key = True ) name = Column(String( 64 )) pub_date = Column(DATE) authors = relationship( 'Author' ,secondary = book_m2m_author,backref = 'books' ) def __repr__( self ): return self .name class Author(base): __tablename__ = 'authors' id = Column(Integer, primary_key = True ) name = Column(String( 32 )) def __repr__( self ): return self .name base.metadata.create_all(engine) #创建表结构 Session_class = sessionmaker(bind = engine) #创建与数据库的会话,class,不是实例 Session = Session_class() b1 = Book(name = "跟A学Python" ) b2 = Book(name = "跟A学linux" ) b3 = Book(name = "跟A学java" ) b4 = Book(name = "跟C学开发" ) a1 = Author(name = "A" ) a2 = Author(name = "B" ) a3 = Author(name = "C" ) b1.authors = [a1,a2] #建立关系 b2.authors = [a1,a2,a3] Session.add_all([b1,b2,b3,b4,a1,a2,a3]) Session.commit() |
结果:
用orm查一下数据
1
2
3
4
5
|
book_obj = Session.query(Book).filter_by(name = "跟A学Python" ).first() print (book_obj.name, book_obj.authors) #这里book_obj.authors只输出name,因为定义类Author时在__repr__(self):定义了返回值 author_obj = Session.query(Author).filter_by(name = "A" ).first() print (author_obj.name , author_obj.books) |
结果:
多对多删除
1.通过书删除作者,删除的是关系。
1
2
3
|
author_obj = Session.query(Author).filter_by(name = "C" ).first() book_obj = Session.query(Book).filter_by(name = "跟A学linux" ).first() book_obj.authors.remove(author_obj) #通过指定书里删除作者,删除的是关系,作者不受影响。 |
2.删除作者的同时也删除关系。
1
2
|
author_obj = Session.query(Author).filter_by(name = "A" ).first() Session.delete(author_obj) #delete删除作者A,关系也会删除掉。 |
结果:
books表
1
|
authors表 |
book_m2m_author表
Python orm基础的更多相关文章
- Python文件基础
===========Python文件基础========= 写,先写在了IO buffer了,所以要及时保存 关闭.关闭会自动保存. file.close() 读取全部文件内容用read,读取一行用 ...
- 3.Python编程语言基础技术框架
3.Python编程语言基础技术框架 3.1查看数据项数据类型 type(name) 3.2查看数据项数据id id(name) 3.3对象引用 备注Python将所有数据存为内存对象 Python中 ...
- Python爬虫基础
前言 Python非常适合用来开发网页爬虫,理由如下: 1.抓取网页本身的接口 相比与其他静态编程语言,如java,c#,c++,python抓取网页文档的接口更简洁:相比其他动态脚本语言,如perl ...
- 小白必看Python视频基础教程
Python的排名从去年开始就借助人工智能持续上升,现在它已经成为了第一名.Python的火热,也带动了工程师们的就业热.可能你也想通过学习加入这个炙手可热的行业,可以看看Python视频基础教程,小 ...
- python/ORM操作详解
一.python/ORM操作详解 ===================增==================== models.UserInfo.objects.create(title='alex ...
- Python爬虫基础之requests
一.随时随地爬取一个网页下来 怎么爬取网页?对网站开发了解的都知道,浏览器访问Url向服务器发送请求,服务器响应浏览器请求并返回一堆HTML信息,其中包括html标签,css样式,js脚本等.我们之前 ...
- 零基础学Python--------第2章 Python语言基础
第2章 Python语言基础 2.1 Python语法特点 2.11注释 在Python中,通常包括3种类型的注释,分别是单行注释.多行注释和中文编码声明注释. 1.单行注释 在Python中,使用 ...
- Python学习基础笔记(全)
换博客了,还是csdn好一些. Python学习基础笔记 1.Python学习-linux下Python3的安装 2.Python学习-数据类型.运算符.条件语句 3.Python学习-循环语句 4. ...
- Python数据分析基础教程
Python数据分析基础教程(第2版)(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1_FsReTBCaL_PzKhM0o6l0g 提取码:nkhw 复制这段内容后 ...
随机推荐
- react 中的 setState
语法:setState(newState [,callback]) 1.只要有入门基础的同学都知道 setState({...}) 是更新组件中的 state 内容 2.但是,setState 是异步 ...
- [计算机-好软推荐]证件照制作的利器,不会PS也没有关系
多年前发现了这一款软件,后来不管电脑是从xp升级到win7,还是从win7升级到win8,我都收藏了它. 我用它主要是制作大头照,然后通过咔嚓鱼冲印,比起一般的冲印店要便宜些. 这个软件是台湾的朋友开 ...
- 【OI】线性筛
如何查找一个范围内的所有素数? 可以是从1~n挨个判断n%i 是否 == 0,也可以从 1~sqr(n) 一个个判断. 相信你们也听说过埃氏筛法,是使用每一个数的倍数筛掉合数!但是!每一个合数要被筛多 ...
- MQTT Android端对比
根据收集到的信息,MQTT的Android端项目有这些 后面打算分别研究下
- 【推荐】微服务分布式企业框架Springmvc+mybatis+shiro+Dubbo+ZooKeeper+Redis
摘要: 主要定位于互联网企业架构,已内置企业信息化系统的基础功能和高效的代码生成工具,包括:系统权限组件.数据权限组件.数据字典组件.核心工具 组件.视图操作组件.工作流组件.代码 ...
- 逻辑频道号---DVB NIT LCN
先介绍NIT,NIT描述如下: 有一点要注意,NIT是对大网的描述,即NIT并不是描述当前的流,而是描述大网的某些或者全部流.如下图,TS流描述1-6共对6个频点不同的TS流进行了描述,具体对哪一个流 ...
- RDA PQ工具使用 (屏参调整)
使用客户规格书,制作屏参文件. 注意:,必填区和计算区,必填区根据屏参的SPEC填写,具体的屏参文件参数通过点击“Calc Sync”生成. 如:HV320WHB-N81的SPEC: 打开“Color ...
- android 手机上运行图像算法
在pc上调试好的图像处理算法想要在android手机上跑一下看看速度需要一下几个步骤 1.建立一个android application,通过ndk调用你写好的图像算法的c/c++ code 2. 然 ...
- 14_传智播客iOS视频教程_OC的数据类型
对比一下OC和C差别,首先第一个是数据类型. C语言的数据类型分哪几类?C语言有哪些数据类型? 基本数据类型当然还包括int的一些修饰符.像short.long.long long.unsigned. ...
- mysql百万数据分页查询速度
百万数据测试 ,; 受影响的行: 时间: .080ms ,; 受影响的行: 时间: .291ms ,; 受影响的行: 时间: .557ms ,; 受影响的行: 时间: .821ms ,; 受影响的行: ...