您的位置:首页 > 数据库

SQLAlchemy 学习(三)

2015-08-21 11:44 190 查看
转载自:http://snoopyxdy.blog.163.com/blog/static/601174402014781473464/

本节将介绍使用orm进行数据的增删改查的例子

首先是对表和类的定义实例,

# -*- coding: utf-8 -*-from sqlalchemy import *from sqlalchemy.orm import *from datetime import datetimeimport sysreload(sys)sys.setdefaultencoding('utf8')
metadata = MetaData()__engine = create_engine('mysql://root:@192.168.150.3/test',convert_unicode=True, echo=True, encoding='UTF-8')
metadata.bind = __engine
product_table = Table(    'product', metadata,    Column('sku', String(20), primary_key=True),    Column('msrp', Numeric))class Product(object):    def __init__(self, sku, msrp, summary=None):        self.sku = sku        self.msrp = msrp        self.summary = summary        self.categories = []        self.prices = []    def __repr__(self):        return '<Product %s>' % self.skumapper(Product, product_table)
Session = sessionmaker(bind=engine, echo_uow=True)session = Session()
p1 = Product('123', 11.22)p2 = Product('456', 33.44)session.add(p1)session.add(p2)session.flush()


1、mapper中使用 exclude_properties

#排除id列名
mapper(Region, region_table, exclude_properties=['id'])

2、使用properties让数据对象属性和表属性进行关联
mapper(Region, region_table, properties=dict(
region_name=region_table.c.name,
region_id=region_table.c.id))

3、子查询映射关联(一般用不到)

average_price = select( [func.avg(product_price_table.c.price)], product_price_table.c.sku==product_table.c.sku)\ .as_scalar() \ .label('average_price')#打印语句print average_price(SELECT avg(product_price.price)FROM product_price, productWHERE product_price.sku = product.sku) AS average_price#执行子查询mapper(Product, product_table, properties=dict( average_price=column_property(average_price)))p = session.query(Product).get('123')print p.sku, p.msrp, p.average_price#打印结果123 12.34 12.34


4、延迟加载

比如数据库存储了BLOB类型的2进制文件,我们只是希望用到这个数据才去加载他,可以这样建立映射关系

product_table = Table('product', metadata,Column('sku', String(20), primary_key=True),Column('msrp', Numeric),Column('image1', Binary),Column('image2', Binary),Column('image3', Binary))mapper(Product, product_table, properties=dict(image1=deferred(product_table.c.image, group='images'),image2=deferred(product_table.c.image, group='images'),image3=deferred(product_table.c.image, group='images')))


5、mapper方法的一些参数

entity_name=None,
always_refresh=False,每次从数据库的查询到的数据都会重写内存数据,所以使用populate_existing()会优于这个参数。
allow_column_override=False,允许关联的属性和列名相同,这样列名就不会被映射了
allow_null_pks=False,允许主键为NULL,如果不设置,当主键为NULL时将不会跳过结构对象生成
batch=True,允许多个对象批处理save操作,如果设置为False,每个对象将会依次入库
column_prefix= None,自动加上映射列名属性的前缀
concrete=False,如果为true,说明使用的具体表继承
extension=None,一个映射的扩展对象或者映射扩展对象数组
inherits=None,另外一个映射对象,用来被继承的
inherit_condition=None,另外一个映射对象,继承的方式
inherit_foreign_keys=None,继承方式的参数
order_by=None,默认的排序方式对这个映射关系查询出的结果
non_primary=False,设定这个是不设置主键的映射
properties=None,一个字段,表示那些属性映射到表中,(不设置将会自动映射)
include_properties=None,一个属性数组,表示哪些属性会映射到表中,没有在数组中出现的属性不会映射到表中
exclude_properties=None,一个属性数组,那些属性确定不包括在数组中
primary_key=None,主键数组
polymorphic_on=None,
polymorphic_identity=None,
polymorphic_fetch='union',
select_table=None,
version_id_col=None

6、在映射中声明关系

一般关系对应有3种方式,1对多,多对多,1对1.

6.1、1对多的关系声明

mapper(Store, store_table)mapper(Region, region_table, properties=dict(   stores=relation(Store)))mapper(Region, region_table, properties=dict(#当两张表有多个外键关系时,SQLAlchemy无法判断用哪个作为外键,可以指定它stores=relation(Store,primaryjoin=(store_table.c.region_id==region_table.c.id))))


6.2、多对多的关系声明

定义两张多对多的表和一张关系关联表

category_table = Table('category', metadata,Column('id', Integer, primary_key=True),Column('level_id', None, ForeignKey('level.id')),Column('parent_id', None, ForeignKey('category.id')),Column('name', String(20)))
product_table = Table('product', metadata,Column('sku', String(20), primary_key=True),Column('msrp', Numeric))
product_category_table = Table('product_category', metadata,Column('product_id', None, ForeignKey('product.sku'), primary_key=True),Column('category_id', None, ForeignKey('category.id'), primary_key=True))
#定义mapper关系mapper(Category, category_table, properties=dict( products=relation(Product, secondary=product_category_table)))
#另外一个关系映射也要声明一下
mapper(Product, product_table, properties=dict( categories=relation(Category, secondary=product_category_table)))


6.3、1对1的关系

1对1是特殊的1对多关系,只需要这样声明即可

mapper(Product, product_table, properties=dict( summary=relation(ProductSummary, uselist=False)))


7、backref避免重复两次声明关系

mapper(Level, level_table, properties=dict( categories=relation(Category, backref='level')))
mapper(Category, category_table, properties=dict( products=relation(Product, secondary=product_category_table, backref='categories')))
#同样可以使用backref()方法来建立另外一个1对1的关系
mapper(ProductSummary, product_summary_table, properties=dict(   product=relation(Product,   backref=backref('summary', uselist=False))))
mapper(Product, product_table)


8、relation函数的参数

backref(relation( )only),反向的关系自动声明

cascade,层叠改变关系,主要用于1对多,当parent改变,Children也会改变,参数是all,delete,save-update,refresh-
expire,merge,expunge,delete-orphan

collection_class,

foreign_keys,外键申明数组

join_depth=None,连接深度

lazy=True,

order_by,排序

passive_deletes=False,如果为true,表示自动删除子关联,当主键为null或者父删除

post_update=False,如果设置为true,SQLAlchemy会分开CRUD操作,否则将会把CRUD操作放在一个声明里

primaryjoin,设定怎么连接父表和子表

remote_side,用于本表关联

secondary,在多对多关系中,用来声明关系表

secondaryjoin,多对多关系,声明父表如何链接关系表

uselist=True,1对1关系时声明

viewonly=False,只读操作连接

9、步入正轨,使用ORM进行查询和修改

两种方式生成session
第一种方式

Session = sessionmaker(bind=engine)


第二种方式

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


sessionmaker接受参数:
bind=None,参数是一个数据库引擎或者连接字符串
binds=None,绑定其他mapper对象或者表
autoflush=True,自动flush
transactional=False,事物操作,当设置为true时,无需使用begin( )来声明事物开始,只需要执行commit()就可以提交事物,回滚使用rollback()
twophase=False,多数据库事物支持回滚
echo_uow=False,输出debug信息
extension=None,扩展字段
weak_identity_map=True,自动回收,如果设置为false,需要手动执行session的expunge( ), clear( ), or purge( )进行回收

10、将数据对象保存到session中

product_table = Table(    'product', metadata,    Column('sku', String(20), primary_key=True),    Column('msrp', Numeric))
class Product(object):    def __init__(self, sku, msrp, summary=None):        self.sku = sku        self.msrp = msrp        self.summary = summary        self.categories = []        self.prices = []    def __repr__(self):        return '<Product %s>' % self.sku
mapper(Product, product_table)
Session = sessionmaker(bind=engine, echo_uow=True)session = Session()p1 = Product('123', 11.22)p2 = Product('456', 33.44)session.add(p1)session.add(p2)session.flush()


11、从session中删除

session.delete(p1)


12、事物的操作

session.begin()session.commit()session.rollback()


13、其他session方法

save( self, obj, entity=None),delete( self, obj ),从下次flush中,删除对象expire( self, obj ),refresh( self, obj )merge( self, obj, entity=None )expunge( self, obj ),在session中删除整个对这个对象的引用update( self, obj, entity=None ),get( self, class_, ident, **kwargs ),load( self, class_, ident, **kwargs )query( self, mapper_or_class, *addtl_entities, **kwargs ),查询clsoe(),摧毁这个sessionexecute( self, clause, params=None, mapper=None, **kwargs ),identity_mapnewdirtydeleted


14、session查询的例子,只有当执行all等操作时,才回去数据库真正的执行操作

query = session.query(Product)query = query.filter_by(msrp=11.22)query = query.limit(3)print query.all() #.first()


15、多表orm联查

query = session.query(Product)query = query.join('categories')query = query.filter_by(name='T-Shirts')print query.all()[<Product 222>]print querySELECT product.sku AS product_sku, product.msrp AS product_msrpFROM product JOIN product_category ON product.sku = product_category.product_id JOIN category ON category.id = product_category.category_idWHERE category.name = ? ORDER BY product.oidjoin方法是inner join,outjoin则是outerjoin#filter方法实例 query = query.filter(or_(Category.c.name=='Pants',   Category.c.name==None))


16、from_statement,从select语句中获取查询条件

session.clear() stmt = select([product_table.c.sku]) query = session.query(Product).from_statement(stmt) for prod in query:    print prod, prod.msrp


17、query对象的一些方法:

add_column( self, column, id=None ),对当前查询对象增加一列

add_entity( self, entity, alias=None, id=None ),对当前查询对象增加一个实体

all( self ),去数据库执行查询操作,然会resultProxy类型

autoflush( self, setting ),自动刷数据库

apply_avg( self, col ),增加SQL AVG,返回query对象

apply_max( self, col ),增加SQL MAX,返回query对象

apply_min( self, col ),增加SQL MIN,返回query对象

apply_sum( self, col ),增加SQL SUM,返回query对象

avg( self, col ),增加SQL avg,去数据库查询

count( self ),去数据库查询,并返回计数

distinct( self ),对整个query对象增加去重复,返回query

filter( self, criterion ),增加过滤对象,返回query

filter_by( self, **kwargs ),增加过滤字典,返回query

first( self ),去数据库返回查询结果的一条

from_statement( self, statement ),传入使用select()函数生成的查询语句,返回query

get( self, ident, reload=False, lockmode=None ),检查当前session是否具有此对象,如果有则

group_by( self, criterion ),分组,返回query

having( self, criterion ),增加having条件,返回query

join( self, prop, id=None, aliased=False, from_joinpoint=False ),新增加一个表,进行from查询,返回query

limit( self, limit ),limit限制,返回query

load( self, ident, raiseerr=True, lockmode=None ),从数据库返回这个实例

max( self, col ),执行SQL MAX

min( self, col, ),执行SQL MIN

offset( self, offset ),偏移量,返回query

one( self ),执行sql,返回结果,如果结果不是一个则抛出异常

options( self, *args ),根据数据中的mapper,返回一个新的query

order_by( self, criterion ),排序,返回query,

outerjoin( self, prop, id=None, aliased=False, from_joinpoint=False ),外联操作,返回query

params( self, *args, **kwargs ),更改现有的query中的查询绑定的值,返回query

populate_existing( self ),返回一个query,刷新所有对象

query_from_parent( cls, instance, property, **kwargs ) (classmethod),从另外一个query继承

reset_joinpoint( self ),重置连接属性,会影响filter_by,join,outerjoin

sum( self, col ),执行sum

with_lockmode( self, mode ),返回query,设置lockmodle

with_parent( self, instance, property=None ),从父query继承

__getitem__( self, item ) (indexing)

__iter__( self ) (iteration)

18、使用一个上下文线程session,tornado的例子

Session = scoped_session(sessionmaker( bind=engine, autoflush=True, transactional=True))session = Session()session2 = Session()session is session2#用完需要调用close来清理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: