SQLAlchemy-对象关系教程ORM-一对多(外键),一对一,多对多

一:一对多

  表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类,然后,在父表类中通过 relationship() 方法来引用子表的类。

一对多的关系中建立双向的关系,这样的话在对方看来这就是一个多对一的关系,在子表类中附加一个 relationship() 方法,并且在双方的 relationship() 方法中使用 relationship.back_populates 方法参数。这样的话子表将会在多对一的关系中获得父表的属性,或者,可以在单一的 relationship() 方法中使用 backref 参数来代替 back_populates 参数。

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent", back_populates="children")
    # 子表类中附加一个 relationship() 方法
    # 并且在(父)子表类的 relationship() 方法中使用 relationship.back_populates 参数

 

  注意:Child.parent是指一个Parent实例,另一方面,Parent.children 是指的一个Child实例列表。

  

# -*- coding:utf-8 -*-
__author__ = 'shisanjun'
import sqlalchemy
from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker,relationship

#创建连接
engine=sqlalchemy.create_engine("mysql+pymysql://admin:admin@192.168.0.121/test2?charset=utf8",echo=True)

#声明ORM映射基类
BASE=declarative_base()

class User(BASE):
    __tablename__="users" #指定表名
    id=Column(Integer,primary_key=True) #建立主键
    name=Column(String(32))
    fullname=Column(String(32))
    password=Column(String(32))

    def __repr__(self): #返回对象时打印显示
        return "name:%s full name:%s password:%s" %(self.name,self.fullname,self.password)

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", back_populates="addresses")

     def __repr__(self):
         return "<Address(email_address='%s')>" % self.email_address

BASE.metadata.create_all(engine)

Session=sessionmaker(bind=engine)
#实例化会话类
session=Session()

jack=User(name='jack',fullname='Jack Bean',password='gjffdd')
jack.addresses = [
    Address(email_address='jack@google.com'),
    Address(email_address='j25@yahoo.com')]

session.add(jack)
session.commit()

jack = session.query(User).filter_by(name='jack').one()
print(jack.addresses)

 

 

 

二:一对一

   一对一是两张表之间本质上的双向关系。 要做到这一点,只需要在一对多关系基础上的父表中使用 uselist 参数来表示。

  

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child = relationship("Child", uselist=False, back_populates="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent", back_populates="child")

三:多对多

  多对多关系会在两个类之间增加一个关联的表。 

  这个关联的表在 relationship() 方法中通过 secondary 参数来表示

  通常的,这个表会通过 MetaData 对象来与声明基类关联

   所以这个 ForeignKey 指令会使用链接来定位到远程的表

双向关系中,两个表类都会包含这个集合。 

指定使用 relationship.back_populates 参数,并且为每一个 relationship() 方法指定共用的关联表

当在父表类的 relationship() 方法中使用 backref参数代替 relationship.back_populates 时,backref 会自动的为子表类加载同样的secondary 参数

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)

 

posted on 2017-08-18 20:37  shisanjun  阅读(1396)  评论(0)    收藏  举报

导航