python - SQLAlchemy 中关系定义的几个问题( 一对一 / 多对多 )
伊谢尔伦
伊谢尔伦 2017-04-18 09:59:25
0
1
1064

2016/11/11

问题

官网关于这一部分的讲解, 不是很详细, 尤其是拿 Parent 和 Child 作为比喻, 感觉不是很形象, 我基于自己的理解,写了对应的的 demo, 但是不是很清楚:

  1. 是否符合最佳实践

  2. 是否漏掉了某些最佳实践?

我看书, 了解到, 实际生产中, 虽然外键可以降低开发成本, 但是许多情况下不推荐外键来关联, 另有其他方法, 不知这句话的内涵是什么?

相关代码

  • 多对多

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'))
伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

membalas semua(1)
大家讲道理

Terima kasih atas jemputan.
ORM SQLchemy sememangnya tidak semudah digunakan seperti Django.
Untuk perhubungan banyak-ke-banyak, memang perlu untuk mentakrifkan jadual perkaitan dengan urutan Apabila medan tambahan perlu ditambahkan pada jadual perkaitan, Django juga perlu mentakrifkan Model yang mengurus jadual.

Selepas mentakrifkan perhubungan ramai-ke-banyak, pertanyaan adalah lebih mudah.
Sebagai contoh, tanya semua Many2 objek yang sepadan dengan Many1 objek m1:

  1. Anda boleh menulis terus:

    kembali m1.many2 # Mengembalikan tatasusunan Many2 objek

  2. Atau pertanyaan yang sangat panjang seperti ini:

    sesi pulangan.pertanyaan(Banyak2).penapis(Banyak2.banyak1.mengandungi(m1)).semua()

  3. Kaedah lain ialah mentakrifkan Kelas jadual persatuan (bukannya mentakrifkan jadual pengurusan secara langsung), dan kemudian menanyakan secara langsung jadual persatuan.

Contoh menggunakan definisi perhubungan banyak-ke-banyak anda adalah seperti berikut:

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

Selain itu, dalam definisi 1 hingga 1 anda, One2 tiada satu hubungan:

one1 = relationship('One1', back_populates='one2')
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan