Heim > Fragen und Antworten > Hauptteil
2016/11/11
官网关于这一部分的讲解, 不是很详细, 尤其是拿 Parent 和 Child 作为比喻, 感觉不是很形象, 我基于自己的理解,写了对应的的 demo, 但是不是很清楚:
是否符合最佳实践
是否漏掉了某些最佳实践?
我看书, 了解到, 实际生产中, 虽然外键可以降低开发成本, 但是许多情况下不推荐外键来关联, 另有其他方法
, 不知这句话的内涵是什么?
多对多
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import (Table, Column, Integer, String, Numeric, DateTime)
from sqlalchemy.orm import relationship
from sqlalchemy import ForeignKey
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()
class Many1(Base):
__tablename__ = 'many1'
id = Column(Integer, primary_key=True, autoincrement=True)
attr1 = Column(String, nullable=False)
many2 = relationship('Many2', back_populates='many1', secondary=many1_many2_table) # 1?? 定义正确?
class Many2(Base):
__tablename__ = 'many2'
id = Column(Integer, primary_key=True, autoincrement=True)
attr2 = Column(String, nullable=False)
many1 = relationship('Many1', back_populates='many2', secondary=many1_many2_table) # 2?? 定义正确?
many1_many2_table = Table('many1_many2', Base.metadata,
Column('many1_id', Integer, ForeignKey('many1.id')),
Column('many2_id', Integer, ForeignKey('many2.id')))
1. 查询 m1 身上所有的 Many2 ( m1 是 Many1 的实例 )
a. return m1.many2 这种能写吗, 其实这种很直观! Elixir中能够这样写
b. session.query(Many2).filter(Many2.many1 == m1).all()
2. 定义多对多, 需要额外定义一张关联表, 难道没有一劳永逸的办法吗? ( 生产数据库中可不止几张关系表, 都要手写? )
一对一
class One1(Base):
__tablename__ = 'one1'
id = Column(Integer, primary_key=True, autoincrement=True)
attr1 = Column(String, nullable=False)
one2 = relationship('One2', back_populates='one1', uselist=False) # 1?? 看官网文档, 只需要添加 uselist 这个参数即可
class One2(Base):
__tablename__ = 'one2'
id = Column(Integer, primary_key=True, autoincrement=True)
attr2 = Column(String, nullable=False)
one1_id = Column(Integer, ForeignKey('one1.id'))
大家讲道理2017-04-18 10:01:25
感谢邀请。
SQLAchemy的ORM使用上确实没有Django简洁。
针多多对多的关系,确实需要与线定义好关联表,当关联表中需要加入额外字段时,Django也需要定义管理表的Model。
定义好多对多的关系后,查询是比较方便的。
例如查询Many1对象m1对应的所有Many2对象:
可以直接写:
return m1.many2 # 返回的是Many2对象的数组
或者非常冗长的这样查询:
return session.query(Many2).filter(Many2.many1.contains(m1)).all()
还有一种是定义关联表Class(而不是直接定义管理表),然后直接查询关联表。
使用你的多对多关系定义示例如下:
if __name__ == '__main__':
engine = create_engine('sqlite:///:memory:')
metadata = Base.metadata
metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
session.add_all([
Many1(id=10, attr1='<10>', many2=[
Many2(id=20, attr2='<20>'),
Many2(id=40, attr2='<40>'),
]),
Many1(id=11, attr1='<10>', many2=[
Many2(id=60, attr2='<60>'),
Many2(id=80, attr2='<80>'),
]),
Many2(id=100, attr2='<100>', many1=[
Many1(id=12, attr1='<12>'),
Many1(id=13, attr1='<13>'),
Many1(id=14, attr1='<14>'),
])
])
session.commit()
# 1. Nice query
print '####Nice query####'
m1 = session.query(Many1).get(10)
for m2 in m1.many2:
print m2.id, m2.attr2
# 2. Bad query
print '####Bad query####'
for m2 in session.query(Many2).filter(Many2.many1.contains(m1)).all():
print m2.id, m2.attr2
另外你的1对1的定义中,One2少一个relation:
one1 = relationship('One1', back_populates='one2')