Flask 数据库多对多自引用关系

上篇介绍的多对多关系是两个模型是之间的多对多关系,关联表联接的是两个明确的实体,还有些情况下只有一个模型,与自己之间存在多对多关系。比如用户之间的关注。表示用户关注其他用户时,只有用户一个实体,没有

第二个实体。如果关系中的两侧都在同一个表中, 这种关系称为自引用关系。

在关注中, 关系的左侧是用户实体,可以称为“关注者”;关系的右侧也是用户实体,但这些是“被关注者”。从概

念上来看,自引用关系和普通关系没什么区别,只是不易理解。下图 是自引用关系的数据库图解,表示用户之间的关注。

本例的关联表是 follows,其中每一行都表示一个用户关注了另一个用户。图中左边表示的一对多关系把用户和 follows 表中的一组记录联系起来,用户是关注者。图中右边表示的一对多关系把用户和 follows 表中的一组记录联系起来,用户是被关注者。

<span style="font-size:18px;">app/models/user.py:关注关联表的模型实现

class Follow(db.Model):
    __tablename__ = 'follows'
    follower_id = db.Column(db.Integer, db.ForeignKey('users.id'),primary_key=True)

   followed_id = db.Column(db.Integer, db.ForeignKey('users.id'),primary_key=True)

   timestamp = db.Column(db.DateTime, default=datetime.utcnow)</span>

SQLAlchemy 不能直接使用这个关联表,因为如果这么做程序就无法访问其中的自定义字段。相反地, 要把这个多对多关系的左右两侧拆分成两个基本的一对多关系,而且要定义成标准的关系。代码如下 所示。

<span style="font-size:18px;">app/models/user.py:使用两个一对多关系实现的多对多关系</span><p><span style="font-size:18px;">
</span></p>
class User(UserMixin, db.Model):
# ...
 followed = db.relationship('Follow',foreign_keys=[Follow.follower_id],
                                      backref=db.backref('follower', lazy='joined'),
                                              lazy='dynamic',
                                              cascade='all, delete-orphan')

 followers = db.relationship('Follow',foreign_keys=[Follow.followed_id],
                                       backref=db.backref('followed', lazy='joined'),
                                               lazy='dynamic',
                                               cascade='all, delete-orphan')

在这段代码中, followed 和 followers 关系都定义为单独的一对多关系。注意,为了消除外键间的歧义, 定义关系时必须使用可选参数 foreign_keys 指定的外键。而且,db.backref() 参数并不是指定这两个关系之间的引用关系,而是回引 Follow 模型。回引中的 lazy 参数指定为 joined。这个 lazy 模式可以实现立即从联结查询中加载相关对

象。例如,如果某个用户关注了 100 个用户,调用 user.followed.all() 后会返回一个列表,其中包含 100 个 Follow 实例,每一个实例的 follower 和 followed 回引属性都指向相应的用户。设定为 lazy=‘joined‘ 模式,就可在一次数据库查询中完成这些操作。如果把lazy 设为默认值 select,那么首次访问 follower 和 followed 属性时才会加载对应的用户,

而且每个属性都需要一个单独的查询, 这就意味着获取全部被关注用户时需要增加 100 次额外的数据库查询。

这两个关系中, User 一侧设定的 lazy 参数作用不一样。 lazy 参数都在“一”这一侧设定,返回的结果是“ 多”这一侧中的记录。上述代码使用的是 dynamic,因此关系属性不会直接返回记录,而是返回查询对象,所以在执行查询之前还可以添加额外的过滤器。

cascade 参数配置在父对象上执行的操作对相关对象的影响。比如,层叠选项可设定为:将用户添加到数据库会话后, 要自动把所有关系的对象都添加到会话中。层叠选项的默认值能满足大多数情况的需求, 但对这个多对多关系来说却不合用。删除对象时,默认的层叠行为是把对象联接的所有相关对象的外键设为空值。 但在关联表中,删除记录后正确的行为应该是把指向该记录的实体也删除, 因为这样能有效销毁联接。这就是层叠选项值delete-orphan 的作用。

cascade 参数的值是一组由逗号分隔的层叠选项,这看起来可能让人有点困惑,但 all 表示除了 delete-orphan 之外的所有层叠选项。设为 all,delete-orphan 的意思是启用所有默认层叠选项,而且还要删除孤儿记录。

时间: 2024-10-05 02:22:27

Flask 数据库多对多自引用关系的相关文章

Flask 数据库多对多关系

数据库使用关系建立记录之间的联系.其中,一对多关系是最常用的关系类型,它把一个记录和一组相关的记录联系在一起.实现这种关系时,要在"多"这一侧加入一个外键,指向"一"这一侧联接的记录.大部分的其他关系类型都可以从一对多类型中衍生. 多对一关系从"多"这一侧看,就是一对多关系. 一对一关系类型是简化版的一对多关系, 限制"多"这一侧最多只能有一个记录.唯一不能从一对多关系中简单演化出来的类型是多对多关系,这种关系的两侧都有多个记

Flask数据库基本操作-SQLAlchemy

Flask数据库D:使用扩展包flask-sqlalchemy来操作数据库(增删改查)E:通过 Python 对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升U:常用的SQLAlchemy字段类型 类型名 python中类型 说明 Integer int 普通整数,一般是32位 SmallInteger int 取值范围小的整数,一般是16位 BigInteger int或long 不限制精度的整数 Float float 浮点数 Numeric decimal.Decim

flask数据库基本操作

数据库基本操作 在Flak-SQLAlchemy中,插入.修改.删除操作,均由数据库会话管理. 会话用db.session表示.在准备把数据写入数据库前,需要先将数据添加到会话中然后调用commit()方法提交会话. 在Flask-SQLAlchemy中,查询操作是通过query对象操作数据. 最基本的查询时返回表中所有数据,可以通过过滤器进行更精确的数据库查询. 定义模型类 一般实际工作中我们会把模型创建到单独的文件中,学习阶段我们先将模型类写在main.py文件中. from flask i

《Entity Framework 6 Recipes》中文翻译系列 (6) -----第二章 实体数据建模基础之使用Code First建模自引用关系 (转)

2-5 使用Code First建模自引用关系 问题 你的数据库中一张自引用的表,你想使用Code First 将其建模成一个包含自关联的实体. 解决方案 我们假设你有如图2-14所示的数据库关系图的自引用表. 图2-14 一张自引用表 按下面的步骤为这张自引用的表及关系建模: 1.在项目中创建一个继承至DbContext上下文的类EF6RecipesContext. 2.使用代码清单2-5创建一个PictureCategoryPOCO(简单CLR对象)实体. 代码单清2-5 创建一个POCO实

Java中如何表示多对多的关系

在数据库中表示多对多的关系可以采取连接表,那么在Java中能不能表示多对多的关系呢?应该如何表示呢?下面提供一种方案: public class Category { private int id; private String name; private Set<Item> items; } public class Item { private int id; private String name; private Set<Category> categories; } Ca

一对多(多对一)关系中的inverse和cascade属性

首先说一下inverse: "inverse" 直译过来就是"反转,使颠倒"的意思,书面化的解释为"是否将关系维护的权力交给对方" 1. 在hibernate中inverse默认是false,也就是己方拥有维护关系的权利, 当然为true的话,就是把维护关系的权利交给了对方 2. 在一对多的关系(多对一)中,通常将一端的inverse设置为false(一端设为true的话会多出更新语句,有性能问题,下面会讲到),而多对多的关系中,inverse的

hibernate(四) 双向多对多映射关系

序言 莫名长了几颗痘,真TM疼,可能是现在运动太少了,天天对着电脑,决定了,今天下午花两小时去跑步了, 现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感觉还是比较容易的,需要理清楚其数据库关系图,那么你就拿下了它.映射文件的配置还是那么些死东西. --WH 一.小疑问的解答 问题一:到这里,有很多学习者会感到困惑,因为他不知道使用hibernate是不是需要自己去创建表,还是hibernate全自动,如果需要自己创建表,那么主外键这种设置也是自己设

非关系型数据库中的「关系」实现

Knowledge Dependence:阅读文本前,你需要了解基本的关系型数据库与非关系型(NoSQL)数据库的概念和区别,以及 MongoDB(Mongoose)的简单实践. ? 这两三年来,伴随着大数据(Big Data)的空前火热,无论是在工程界还是科研界,非关系型数据库(NoSQL)都已经成为了一个热门话题. 相比于传统的关系型数据库,非关系型数据库天生从理念上就给数据存储提供了一种新的思路.而在实际应用中,它往往更轻巧灵活.扩展性高,并且更能胜任高性能.大数据量的场景. 值得一提的是

EJB3 jpa 数据库表的映射关系

1)多对一映射关系(单向) 使用外键关联,在外键的选取上以多的一方为主,即外键要在多的一方体现出来 @Entity public class Company implements Serializable{ @Id @Column(name = "c_id") private int id; private String name; } @Entity public class Employee implements Serializable { @Id @Column(name=&q