찾다

 >  Q&A  >  본문

python - SQLAlchemy 中关系定义的几个问题( 一对一 / 多对多 )

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'))
伊谢尔伦伊谢尔伦2772일 전1065

모든 응답(1)나는 대답할 것이다

  • 大家讲道理

    大家讲道理2017-04-18 10:01:25

    초대해주셔서 감사합니다.
    SQLAchemy의 ORM은 실제로 Django만큼 사용하기 쉽지 않습니다.
    다대다 관계의 경우 스레드를 사용하여 연관 테이블을 정의하는 것이 실제로 필요합니다. 연관 테이블에 추가 필드를 추가해야 하는 경우 Django는 테이블을 관리하는 모델도 정의해야 합니다.

    다대다 관계를 정의한 후 쿼리하는 것이 더 편리합니다.
    예를 들어 Many1 개체 m1에 해당하는 모든 Many2 개체를 쿼리합니다.

    1. 직접 작성할 수 있습니다:

      return m1.many2 # Many2 객체의 배열을 반환합니다

    2. 또는 다음과 같이 매우 긴 쿼리:

      session.query(Many2).filter(Many2.many1.contains(m1)).all() 반환

    3. 또 다른 방법은 관리 테이블을 직접 정의하지 않고 연관 테이블 Class를 정의한 후 연관 테이블을 직접 쿼리하는 방법이다.

    다대다 관계 정의를 사용하는 예는 다음과 같습니다.

    으아악

    또한 1:1의 정의에서 One2에는 하나의 관계가 누락되어 있습니다.

    으아악

    회신하다
    0
  • 취소회신하다