flask 定义数据关系(多对一)

时间:2023-03-09 16:35:40
flask 定义数据关系(多对一)
多对一

一对多关系反过来就是多对一关系,这两种关系模式分别从不同的视角出发。一个作者拥有多篇文章,反过来就是多篇文章属于同一个作者。为了便于区分,我们使用居民和城市来演示多对一关系:多个居民住在同一个城市。多对一关系如下:

flask 定义数据关系(多对一)

在例子中,Citizen类表示居民,City类表示城市。建立多对一关系后,我们将在Citizen类中创建一个标量关系属性city,调用它可以获取单个City对象。

我们在前面介绍过,关系属性在关系模式的出发侧定义。当出发点在“多”这一侧时,我们希望在Citizen类中添加一个关系属性city来获取对应的城市对象,因为这个关系属性返回单个值,我们称之为标量关系属性。在定义关系时,外键总是在“多”这一侧定义,所以在多对一关系中外键和关系属性都定义在“多”这一侧,即City类中:

app.py:建立多对一关系

class Citizen(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(70), unique = True)
city_id = db.Column(db.Integer, db.ForeignKey('city.id'))
city = db.relationship('City') class City(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(30), unique = True)

这时定义的 city关系属性是一个标量关系(返回单一数据)。当Citizen.city被调用时,SQLAlchemy会根据外键字段city_id存储的值查找对应的City对象并返回,即居民记录对应的城市记录。

>>> from app import Citizen
>>> from app import db
>>> city1 = City(name = 'DaLian')
>>> citizen1 = Citizen(name = 'Xia')
>>> citizen1.city= city1
>>> citizen1.city
<City (transient 54277680)>

当建立双向关系时,如果不使用backref,那么一对多和多对一关系模式在定义上完全相同,这时可以将一对多和多对一关系模式。我们通常都会为一对多或多对一建立双向关系,这时将弱化这两种关系的区别,一律称为一对多关系。

class Citizen(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(70), unique = True)
city_id = db.Column(db.Integer, db.ForeignKey('city.id'))
city = db.relationship('City', back_populates='citizen') def __repr__(self):
return '<Citizen %r>' % self.name class City(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(30), unique = True)
#back_populates的值为另一侧的关系属性名
#relationship函数的第一个参数是另一侧的模型名(类型)
citizen = db.relationship('Citizen', back_populates='city') >>> from app import Citizen, City, db
>>> city1 = City(name = 'DaLian')
>>> citizen1 = Citizen(name = 'xiaxiaoxu')
>>> citizen2 = Citizen(name = 'xufengchai')
>>> citizen1.city = city1
>>> citizen2.city = city1
>>> city1.citizen
[<Citizen 'xiaxiaoxu'>, <Citizen 'xufengchai'>]
>>> citizen2.city
<City 'DaLian'>
>>> citizen1.city
<City 'DaLian'>