SQLAlchemy使用笔记--SQLAlchemy ORM(二)
2015-12-15 20:34
585 查看
参考:
http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship
http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#working-with-related-objects
relationship中的backref参数使用形式:
可以使用user.addresses 从user获取address 和,使用address.users 虫address获取user
backref 会在User跟Address上都加上关系,它本质是:
relationship中的
address 会自动的添加
这样在child添加删除parent或者parent添加删除child时,无需对中间表进行操作,直接添加删除即可。
也可以 使用类来创建中间表,这样可以在中间表中保存一些其他的信息。但是就不能想前面一样自动对中间表进行操作。
在User上可以直接使用join(Address) 因为只有一个外建在User和Address之间,其他join形式:
使用外链接
当query中有多个实体点使用,使用join默认join追左边的那个,
例如:
如果想自定使用join那个表,可以使用select_form
等价于:
user.addresses 可以像user中其他属性一样在filter使用==、!=、any等等。
http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship
http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#working-with-related-objects
建立表之间带关系
建立外建
在address添加user的外键[code]from sqlalchemy import ForeignKey, Column, String, Integer from sqlalchemy.orm import relationship class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) fullname = Column(String) password = Column(String) class Address(Base): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email_address = Column(String, nullable=False) user_id = Column(Integer, ForeignKey('users.id')) user = relationship('User', backref=backref('addresses', order_by=id))
relationship中的backref参数使用形式:
[code]backref="addresses" #直接使用表名的字符串 backref=backref('addresses') #使用backref函数 backref=backref('addresses', order_by=id)) #brackref函数可以添加参数,详见http://docs.sqlalchemy.org/en/rel_1_0/orm/backref.html#backref-arguments
可以使用user.addresses 从user获取address 和,使用address.users 虫address获取user
backref 会在User跟Address上都加上关系,它本质是:
[code]from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship Base = declarative_base() class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) name = Column(String) addresses = relationship("Address", back_populates="user") class Address(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) email = Column(String) user_id = Column(Integer, ForeignKey('user.id')) user = relationship("User", back_populates="addresses")
relationship中的
添加
[code]>>> jack.addresses = [ ... Address(email_address='jack@google.com'), ... Address(email_address='j25@yahoo.com')]
获取
[code]>>> jack.addresses[1] <Address(email_address='j25@yahoo.com')> >>> jack.addresses[1].user <User(name='jack', fullname='Jack Bean', password='gjffdd')>
commit
[code]session.add(jack) session.commit()
address 会自动的添加
one to many 关系
[code]class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child", backref="parent") class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id'))
many to one 关系
[code]class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref="parents") class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True)
one to one 关系
[code]from sqlalchemy.orm import backref class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref=backref("parent", uselist=False)) class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True)
many to many 关系
需要一个中间表和在relatonship 添加secondary参数[code]association_table = Table('association', Base.metadata, Column('left_id', Integer, ForeignKey('left.id')), Column('right_id', Integer, ForeignKey('right.id')) ) class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary=association_table, backref="parents") class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True)
这样在child添加删除parent或者parent添加删除child时,无需对中间表进行操作,直接添加删除即可。
[code]parent.children.append(child) child.parents.append(parent)
也可以 使用类来创建中间表,这样可以在中间表中保存一些其他的信息。但是就不能想前面一样自动对中间表进行操作。
[code]class Association(Base): __tablename__ = 'association' left_id = Column(Integer, ForeignKey('left.id'), primary_key=True) right_id = Column(Integer, ForeignKey('right.id'), primary_key=True) extra_data = Column(String(50)) child = relationship("Child", back_populates="parents") parent = relationship("Parent", back_populates="children") class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Association", back_populates="parent") class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True) parents = relationship("Association", back_populates="child")
join 操作
可以使用Query.join()[code]>>> session.query(User).join(Address).\ ... filter(Address.email_address=='jack@google.com').\ ... all() [<User(name='jack', fullname='Jack Bean', password='gjffdd')>]
在User上可以直接使用join(Address) 因为只有一个外建在User和Address之间,其他join形式:
[code]query.join(Address, User.id==Address.user_id) # explicit condition query.join(User.addresses) # specify relationship from left to right query.join(Address, User.addresses) # same, with explicit target query.join('addresses') # same, using a string
使用外链接
[code]query.outerjoin(User.addresses) # 默认是左外连接。
当query中有多个实体点使用,使用join默认join追左边的那个,
例如:
[code]query = session.query(User, Address).join(User) # 报错 query = session.query(Address, User).join(User) # 正确
如果想自定使用join那个表,可以使用select_form
[code]query = Session.query(User, Address).select_from(Address).join(User)
alias 别名
如果想join自己,可以使用别名[code]from sqlalchemy.orm import aliased adalias1 = aliased(Address) adalias2 = aliased(Address) for username, email1, email2 in \ session.query(User.name, adalias1.email_address, adalias2.email_address).\ join(adalias1, User.addresses).\ join(adalias2, User.addresses).\ filter(adalias1.email_address=='jack@google.com').\ filter(adalias2.email_address=='j25@yahoo.com'): print(username, email1, email2)
使用子查询
直接看官方文档的例子:[code]>>> from sqlalchemy.sql import func >>> stmt = session.query(Address.user_id, func.count('*').\ ... label('address_count')).\ ... group_by(Address.user_id).subquery() >>> for u, count in session.query(User, stmt.c.address_count).\ ... outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id): ... print(u, count) <User(name='ed', fullname='Ed Jones', password='f8s7ccs')> None <User(name='wendy', fullname='Wendy Williams', password='foobar')> None <User(name='mary', fullname='Mary Contrary', password='xxg527')> None <User(name='fred', fullname='Fred Flinstone', password='blah')> None <User(name='jack', fullname='Jack Bean', password='gjffdd')> 2
使用EXISTS
看官方文档的例子:[code]>>> from sqlalchemy.sql import exists >>> stmt = exists().where(Address.user_id==User.id) SQL>>> for name, in session.query(User.name).filter(stmt): ... print(name) jack
等价于:
[code]>>> for name, in session.query(User.name).\ ... filter(User.addresses.any()): ... print(name) jack
user.addresses 可以像user中其他属性一样在filter使用==、!=、any等等。
[code]query.filter(Address.user == someuser) query.filter(Address.user != someuser) query.filter(Address.user == None) query.filter(User.addresses.contains(someaddress)) query.filter(User.addresses.any(Address.email_address == 'bar'))# also takes keyword arguments: query.filter(User.addresses.any(email_address='bar')) query.filter(Address.user.has(name='ed')) session.query(Address).with_parent(someuser, 'addresses')
相关文章推荐
- win7安装Oracle11g出错INS-30131
- Memcache mutex设计模式
- Oracle使用%type类型的变量输出结果
- SQL SERVER 内存学习系列(一)
- 如何成为一个优秀的 MySQL DBA
- mysql命令
- 获得mysql内容,生成xml文件,另外,为了webservice发送
- Oracle 列转行函数 Listagg()
- 关于oracle with as用法
- Mysql Cluster基于时间点的恢复
- 跳转连接oracle
- SQL Server学习记录之语句优化
- Windows64安装Redis及其管理工具RedisStudio
- oracle命令行操作
- mysql更改表结构:添加、删除、修改字段、调整字段顺序
- Mysql相关
- java + memcached安装
- cmd运行现有的sql文件(MySQL)出现SOURCE error 2
- mysql的事务
- MYSQL group_concat()查询关联数据一条显示