sqlalchemy 表关系之一对一

发布时间:2018-06-25 编辑:汤利军 阅读:

今天我们就讲讲sqlalchemy最后一种关系:一对一
  
首先,我们先创建user(父表)、arctire(子表)两张表,代码如下:

#父表
class User(Base):
    __tablename__ = "user"
    id = Column(Integer , primary_key=True , autoincrement=True)
    name = Column(String(50) , nullable=False)

#从表
class Arctire(Base):
    __tablename__ = "arctire"
    id = Column(Integer , primary_key=True , autoincrement=True)
    title = Column(String(50) , nullable=False)
 
    uid = Column(Integer,ForeignKey("user.id"))
    author = relationship("User" , backref="arctires")

表创建成功后,先不急着往表中添加数据,我们先查看下user.arctires 类型,代码如下

user = User(name = "tom")
arctire1 = Arctire(title = "title 1")
arctire2 = Arctire(title = "title 2")
print(type(user.arctires))

运行上述代码,结果如下:


我们再 from sqlalchemy.orm.collections import InstrumentedList ,鼠标选中红色字体部分,双击进去。


结合上面两图,我们可知 user.arctires 的数据类型是 list。地球人都知道list有个append方法,下面我们就通过append这个方法来添加数据,代码如下
user = User(name = "tom")
arctire1 = Arctire(title = "title 1")
arctire2 = Arctire(title = "title 2")
user.arctires.append(arctire1)
user.arctires.append(arctire2)
session.add(user)
session.commit()

运行上述代码,结果如下:


OK,由上可知,数据已成功添加到数据表中。眼尖的小伙肯定发现,目前为止,这两张表还不是一对一关系,而是一对多。

上面讲的主要是让大伙知道 user.arctires数据类型,因为我们要做一对一,关键点就在这。接下来,为了方便演示一对一关系,我们重新新建一张UserExtend表(建议注释Arctire 模型),代码如下:(注意需在user表中添加 extends = relationship("UserExtend");)

class UserExtend(Base):
    __tablename__ = "extend"
    id = Column(Integer , primary_key=True , nullable=False)
    city = Column(String(50) , nullable=False)
    uid = Column(Integer , ForeignKey("user.id"))
    user = relationship("User" , backref="extends")

我们先删除数据库的user、arctire表。然后在运行上诉代码,若无出错信息,则创建表成功。

接下来我们先看看 user.extend数据类型。代码如下
user = User(name = "tom")
extend = UserExtend(city = "shenzhen")
print(type(user.extends))

运行上诉代码,结果报错,报错信息如下:


为什么会报错?我们先不去谈报错的原因,我们先看看两个模型的relation属性。嘿嘿!!发现什么没???啥,没发现!!好吧,哪我就告诉大伙吧。
  
因为我们在User模型中定义了relationship属性,并赋值给 extends ,而我们又在UserExtend模型中定义了backref="extends",造成了冲突。解决办法:

1、去掉UserExtend模型中的backref属性
  
2、去掉User模型中的relatship属性

我们就试试第一种吧!(第二中我们下面讲代码优化时会讲到)

user = relationship("User")

我们再重新运行以下代码(查看 user.extends数据类型)

Base.metadata.drop_all()
Base.metadata.create_all()
user = User(name = "tom")
extend = UserExtend(city = "shenzhen")
print(type(user.extends))

没有报错!运行结果如下:


由上图可知,user.extends结果也是list类型,很显然我们这两张表还不是一对一关系,要实现我们所讲的一对一,其实很简单。只需在一对多关系基础上,在父模型的relation属性添加一个uselist参数进去,并将其值设为False(uselist字面意思为使用list,默认值为True:表示允许使用list);代码如下(红色文字为添加部分)

class User(Base):
    __tablename__ = "user"
    id = Column(Integer , primary_key=True , autoincrement=True)
    name = Column(String(50) , nullable=False)
    extends = relationship("UserExtend",uselist=False)

OK,我们再删除、创建模型,再查看 user.extends数据类型!运行结果如下



嗯、结果终于不是list类型了,看的都吐了!哪为啥是NoneType类型呢?原因很简单,因为我们user表中没有数据,不信我们可以试试



最后一个问题?我们怎么证明这两张表是一对一关系??

方法:向表中插入数据,然后再检测user.extend类型,如果运行结果为 <class '__main__.UserExtend'> ,说明这两张表是一对一关系。截图如下



最后我们对代码进行优化一下,去掉User模型的relationship属性,直接在UserExtend模型中定义,代码如下:(backref方法需从sqlalcehmy.orm中导入

user = relationship("User",backref=backref("extend" ,uselist=False))

上诉代码一样能实现一对一效果,在这里我就不演示了,有兴趣的可以试试。



 

 
 


关注我

图文推荐

云标签

友链交换