sqlalchemy使用
1.SQLAlchemy的作用
ORM对象关系映射技术
2.SQLAlchemy安装
pip install SQLAlchemy
查看SQLAlchemy版本
3.生成数据库连接
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DB_CONNECT_STRING = 'postgresql+psycopg2://postgres:@localhost:5432/postgres'
engine = create_engine(DB_CONNECT_STRING)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
DB_CONNECT_STRING:数据库连接字符串
engine:创建数据库引擎
DB_Session:数据库会话工厂,用于创建数据库连接实例
session:数据库会话实例,可以理解为一个数据库连接, SQLAlchemy 自己维护了一个数据库连接池(默认 5 个连接),因此初始化一个会话的开销并不大。
4.直接执行sql
print(session.execute('select * from "user" where id = 1').first())
print(session.execute('select * from "user" where id = :id', {'id': 1}).first())
运行结果:
5.sqlalchemy一般使用的是它的ORM特性,声明模型Model
from sqlalchemy import Column,String,Integer
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__='user'
id=Column(Integer,primary_key=True)
name=Column(String(50))
# 属性名可以和字段名不一致
from_=Column('from',String(50))
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
基类Base,是一个model和数据库表管理类。
通过继承Base,可自动实现model和数据库表的关联。
create_all(engine) 会找到 BaseModel 的所有子类,并在数据库中建立这些表。
drop_all() 则是删除这些表。
6.批量插入
# 一次插入10000
start = time.time()
for i in range(10000):
user = User()
user.name = str(i)
session.add(user)
session.commit()
end = time.time()
print(end - start)
start = time.time()
session.execute(User.__table__.insert(),
[{'name': str(i)} for i in range(10000)]
)
session.commit()
end = time.time()
print(end - start)
运行结果:
使用非ORM的方式批量插入可以大幅提高效率
7.增删改查
session是关系型数据库中的事务。
1)增加记录
user=User(name="shijingjing07")
session.add(user)
session.commit()
必须commit,才能真正写入数据库
2)删除记录
usr=session.query(User).first()
session.delete(usr)
session.commit()
3)更新记录
usr=session.query(User).first()
usr.name="icefinger"
session.add(usr)
session.commit()
4)查询记录
过滤器:
#==
usr=session.query(User).filter(User.name=="icefinger").first()
print(usr.id)
#!=
usr=session.query(User).filter(User.name!="icefinger").first()
print(usr.id)
#like
usr=session.query(User).filter(User.name.like("icefinger%")).first()
print(usr.id)
#in
usr=session.query(User).filter(User.name.in_(["icefinger","tomcat","james"])).first()
print(usr.id)
#not in
usr=session.query(User).filter(~User.name.in_(["icefinger","tomcat","james"])).first()
print(usr.id)
#is null
usr=session.query(User).filter(User.name==None).first()
print(usr.id)
usr=session.query(User).filter(User.name.is_(None)).first()
print(usr.id)
#and
from sqlalchemy import and_
usr=session.query(User).filter(and_(User.name=="icefinger",User.id=="2")).first()
print(usr.id)
#or
from sqlalchemy import or_
usr=session.query(User).filter(or_(User.name=="icefinger",User.id=="3")).first()
print(usr.id)
返回值:
#first,使用limit返回第一行
print("--first--")
usr=session.query(User).filter(or_(User.name=="icefinger",User.id=="3")).first()
print(usr.id)
#all,返回所有行
print("--all--")
usrlist=session.query(User).filter(or_(User.name=="icefinger",User.id=="3")).all()
for usr in usrlist:
print(usr.id)
#one,返回行数只能是一条
print("--one--")
try:
usr = session.query(User).filter(or_(User.name == "icefinger", User.id == "3")).one()
print(usr)
except:
print("must be one")
#one_on_none,返回行数只能是一条,或none
print("--one_or_none--")
usr = session.query(User).filter(and_(User.name == "icefinger", User.id == "2")).one_or_none()
print(usr)
#scalar,同one_on_none,返回行数只能是一条,或none
print("--scalar--")
usr = session.query(User).filter(or_(User.name == "icefinger", User.id == "2")).scalar()
print(usr)
运行结果:
统计个数:
print("--count1--")
count=session.query(User).count()
print(count)
print("--count2--")
count = session.query(func.count('*')).select_from(User).scalar()
print(count)
8.其他常用语法
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, func
DB_CONNECT_STRING = 'postgresql+psycopg2://postgres:@localhost:5432/postgres'
engine = create_engine(DB_CONNECT_STRING)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
BaseModel = declarative_base()
class User(BaseModel):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(30))
BaseModel.metadata.drop_all(engine)
BaseModel.metadata.create_all(engine)
user = User(name='a')
session.add(user)
user = User(name='b')
session.add(user)
user = User(name='a')
session.add(user)
user = User()
session.add(user)
session.commit()
query = session.query(User)
print(query) # 显示SQL 语句
print(query.statement) # 同上
for user in query: # 遍历时查询
print(user.name)
print(query.all()) # 返回的是一个类似列表的对象
print(query.first().name) # 记录不存在时,first() 会返回 None
# print query.one().name # 不存在,或有多行记录时会抛出异常
print(query.filter(User.id == 2).first().name)
print(query.get(2).name) # 以主键获取,等效于上句
print(query.filter('id = 2').first().name) # 支持字符串
query2 = session.query(User.name)
print(query2.all()) # 每行是个元组
print(query2.limit(1).all()) # 最多返回 1 条记录
print(query2.offset(1).all()) # 从第 2 条记录开始返回
print(query2.order_by(User.name).all())
print(query2.order_by('name').all())
print(query2.order_by(User.name.desc()).all())
print(query2.order_by('name desc').all())
print(session.query(User.id).order_by(User.name.desc(), User.id).all())
print(query2.filter(User.id == 1).scalar()) # 如果有记录,返回第一条记录的第一个元素
print(session.query('id').select_from(User).filter('id = 1').scalar())
print(query.count())
print(session.query(func.count('*')).select_from(User).scalar())
print(session.query(func.current_timestamp()).scalar()) # 使用func调用数据库函数
9.替换一个已有主键的记录
user = User(id=1, name='ooxx')
session.merge(user)
session.commit()
10.关系-一对多
1)如下图所示,一个用户可能对应多个地址
from sqlalchemy import create_engine,and_,or_,func
from sqlalchemy import Table,Column,String,Integer,ForeignKey
from sqlalchemy.orm import relationship,sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine=create_engine("postgresql://postgres:sj1107@localhost:5432/sampledb")
Session=sessionmaker(bind=engine)
session = Session()
Base = declarative_base(bind=engine)
class User(Base):
__tablename__='user'
id=Column(Integer,primary_key=True)
addresses=relationship('Address')
class Address(Base):
__tablename__='address'
id=Column(Integer,primary_key=True)
user_id=Column(Integer,ForeignKey('user.id'))
if __name__ == "__main__":
Base.metadata.create_all()
u=User()
session.add(u)
session.commit()
a1=Address(user_id=u.id)
a2=Address(user_id=u.id)
session.add(a1)
session.add(a2)
session.commit()
print(u.addresses)
运行结果:
ForeignKey:外键,制定了user_id和User的关系
relationship:绑定了两个Model的联系,通过User直接得到所有的地址。
2)根据address获取user:
address只能获得user_id,然后根据user_id获取user
能不能通过address直接获取user呢?在model里,添加relationship关系就可以了。
class User(Base):
__tablename__='user'
id=Column(Integer,primary_key=True)
addresses=relationship('Address')
class Address(Base):
__tablename__='address'
id=Column(Integer,primary_key=True)
user_id=Column(Integer,ForeignKey('user.id'))
user=relationship('User')
运行结果:
3)上例中两个model中都添加relationship,看起来很繁琐,能不能只指定一个,另一个默认就可以访问呢?
backref参数就可以了。
class User(Base):
__tablename__='user'
id=Column(Integer,primary_key=True)
addresses=relationship('Address',backref="user")
class Address(Base):
__tablename__='address'
id=Column(Integer,primary_key=True)
user_id=Column(Integer,ForeignKey('user.id'))
运行结果:
11.关系-多对多
user和address关系为多对多,即一个user对应多个address,一个address对应多个user
多对多需要中间表来关联
#定义中间表,关联多对多关系
user_address_table =Table(
'user_address',Base.metadata,
Column('user_id',Integer,ForeignKey('user.id')),
Column('address_id',Integer,ForeignKey('address.id'))
)
class User(Base):
__tablename__='user'
id=Column(Integer,primary_key=True)
addresses=relationship('Address',secondary=user_address_table)
class Address(Base):
__tablename__='address'
id=Column(Integer,primary_key=True)
users=relationship('User',secondary=user_address_table)
if __name__ == "__main__":
# Base.metadata.create_all()
u1=User()
u2=User()
session.add(u1)
session.add(u2)
session.commit()
a1=Address(users=[u1,u2])
a2 = Address(users=[u1, u2])
session.add(a1)
session.add(a2)
session.commit()
print(u1.addresses)
print(a1.users)
session.delete(u1)
print(a1.users)
运行结果:
12.连接表
上例提到,可以使用relationship关联表,relationship虽然看上去比较方便,但是比较复杂,且存在性能问题,所以一般自己join
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, func, ForeignKey
DB_CONNECT_STRING = 'postgresql+psycopg2://postgres:@localhost:5432/postgres'
engine = create_engine(DB_CONNECT_STRING)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
BaseModel = declarative_base()
class User(BaseModel):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(30))
class Friend(BaseModel):
__tablename__ = 'friend'
id = Column(Integer, primary_key=True)
name = Column(String(30))
user_id = Column(Integer, ForeignKey('user.id'))
BaseModel.metadata.drop_all(engine)
BaseModel.metadata.create_all(engine)
user = User(name='a')
session.add(user)
user = User(name='b')
session.add(user)
session.commit()
friend = Friend(name='er',user_id=1)
session.add(friend)
friend = Friend(name='tr',user_id=1)
session.add(friend)
session.commit()
# 拥有朋友的用户,方法一
query = session.query(User).join(Friend, Friend.user_id == User.id)
print(query.all())
# 拥有朋友的用户,方法二
query = session.query(User).filter(
User.id == Friend.user_id
)
print(query.all())
# 所有用户,及用户对应的朋友
query = session.query(User, Friend).outerjoin(Friend, Friend.user_id == User.id)
print(query.all())
运行结果:
【1.png】
13.扩展基类
declarative_base基类,是一个model和数据库表管理类。
我们可以定义一个扩展基类,抽象model的公共属性,和一些公共的数据库操作函数。
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, func, ForeignKey
DB_CONNECT_STRING = 'postgresql+psycopg2://postgres:@localhost:5432/postgres'
engine = create_engine(DB_CONNECT_STRING)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
BaseModel = declarative_base()
class CommonModel(object):
id = Column(Integer, primary_key=True)
@classmethod
def get_one_by_id(cls, session, id):
try:
query = session.query(cls).filter(cls.id == id)
return query.one_or_none()
except Exception as e:
return None
@classmethod
def get_all(cls, session,query_columns=None, filter_columns=None, offset=None, limit=None,order_by=None):
try:
if not query_columns:
query = session.query(cls)
else:
query = session.query(*query_columns)
if filter_columns:
query = query.filter(*filter_columns)
if limit:
query = query.limit(limit)
if offset:
query = query.offset(offset)
if order_by:
query = query.order_by(order_by)
return query.all()
except Exception as e:
return None
@classmethod
def get_count(cls, session, filter_columns=None):
try:
query = session.query(cls)
if filter_columns:
query = query.filter(*filter_columns)
count = query.count()
return count
except Exception as e:
return None
class User(BaseModel, CommonModel):
__tablename__ = 'user'
name = Column(String(30))
# BaseModel.metadata.drop_all(engine)
# BaseModel.metadata.create_all(engine)
result = User.get_one_by_id(session, 1)
print(result)
result = User.get_all(session)
print(result)
result = User.get_count(session)
print(result)
运行结果:
sqlalchemy使用的更多相关文章
- sqlalchemy学习
sqlalchemy官网API参考 原文作为一个Pythoner,不会SQLAlchemy都不好意思跟同行打招呼! #作者:笑虎 #链接:https://zhuanlan.zhihu.com/p/23 ...
- tornado+sqlalchemy+celery,数据库连接消耗在哪里
随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知. 最近老是发现数据库的连接数如果 ...
- 冰冻三尺非一日之寒-mysql(orm/sqlalchemy)
第十二章 mysql ORM介绍 2.sqlalchemy基本使用 ORM介绍: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似pyt ...
- Python 【第六章】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
- SQLAlchemy(一)
说明 SQLAlchemy只是一个翻译的过程,我们通过类来操作数据库,他会将我们的对应数据转换成SQL语句. 运用ORM创建表 #!/usr/bin/env python #! -*- coding: ...
- sqlalchemy(二)高级用法
sqlalchemy(二)高级用法 本文将介绍sqlalchemy的高级用法. 外键以及relationship 首先创建数据库,在这里一个user对应多个address,因此需要在address上增 ...
- sqlalchemy(一)基本操作
sqlalchemy(一)基本操作 sqlalchemy采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型. 安装 需要安装MySQLdb pip install ...
- python SQLAlchemy
这里我们记录几个python SQLAlchemy的使用例子: 如何对一个字段进行自增操作 user = session.query(User).with_lockmode('update').get ...
- Python-12-MySQL & sqlalchemy ORM
MySQL MySQL相关文章这里不在赘述,想了解的点击下面的链接: >> MySQL安装 >> 数据库介绍 && MySQL基本使用 >> MyS ...
- 20.Python笔记之SqlAlchemy使用
Date:2016-03-27 Title:20.Python笔记之SqlAlchemy使用 Tags:python Category:Python 作者:刘耀 博客:www.liuyao.me 一. ...
随机推荐
- Phpcms之L()函数
.phpcms\languages\zh-cn 中文语言包2.phpcms\languages\en 英文语言包 phpcms v9语言包建立 在phpcms v9二次开发之模型类的应用 ...
- SSH框架学习
首先,SSH不是一个框架,而是多个框架(struts+spring+hibernate)的集成,是目前较流行的一种Web应用程序开源集成框架,用于构建灵活.易于扩展的多层Web应用程序. 集成SSH框 ...
- 全局安装 vue
通过npm命令安装vuejs在用 Vue.js 构建大型应用时推荐使用 NPM 安装,NPM 能很好地和诸如 Webpack 或Browserify 的 CommonJS 模块打包器配合使用.(以下操 ...
- 用Python读取大文件
通常我们在读取文件的时候,会用到read(), readline(), readlines(). 通常可能会有这样的用法: def test1(): with open("/tmp/test ...
- .NET 垃圾回收机制要点整理
1. .NET资源分托管资源和非托管资源,对于托管资源,.NET GC可以很好的回收无用的垃圾,而对于非托管(例如文件访问,网络访问等)需要手动清理垃圾(显式释放). 2. 非托管资源的释放,.NET ...
- linux(red hat)下安装jenkins
Jenkins的安装能够分为在线安装和下载软件本地安装.我这里用的是另外一种方法,将其下载后是一个应用程序直接点击安装就能够.等安装完后配置一下jdk的路径就ok啦!接下来进行具体的说明: 一.前提 ...
- 【zend studio】如何添加已存在的git项目
1.在zend里面新增项目crm2 2.win下进入crm2目录,右键选择 Git Bash Here,进项git clone操作 3.进入下载下来的GIT项目目录,选择复制,然后返回上一目录crm2 ...
- Web Service——CXF发布REST服务
1. 什么是REST REST,英文representational state transfer(表象性状态转变)或者表述性状态转移,REST是web服务的一种架构风格,使用HTTP.URI.XML ...
- maven 继承关系和聚合
maven继承管理 让版本的管理只在一个地方改变 modules用于聚合,把执行的项目都放到同一的地方用module包括,可以省去一个个项目去mvn install,这样可以所有项目一次聚合 mvn ...
- BeanUtils 装载java bean
Topic topic=new Topic(); Enumeration<String> enums=request.getParameterNames(); try { while(en ...