【Flask】Flask数据模型关系

数据模型关系

一对多

如上所示,一个作者关联多个文章,暂时认定,一篇文章只能有一个作者。

作者以及文章的类定义如下所示:

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)
    email = db.Column(db.String(128))
​
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), index=True)
    description = db.Column(db.Text)

一对多的建立步骤

现在需要在数据库中,将作者和文章的关系关联成一对多的关系,具体操作如下:

  1. 定义外键

    外键(Foreign key) 用来在 B 表存储 A 表的主键值,作为与 A 表的关系字段。

    由于外键只能够存储单一数据,所以外键常在 “多” 的一侧定义,一个作者对应多个文章,因此需要在文章模型中添加作者的关系字段,记录作者的主键值,代码如下:

    class Article(db.Model):
        ...
        author_id = db.Column(db.Integer, db.ForeignKey('author.id'))

  2. 定义关系属性

    关系属性的定义主要是用来标记该类与那个类建立了关系,常常在 “一” 的一侧进行定义,关系属性能够返回多个记录,也称之为集合关系属性。

    在作者和文章的关系中,就需要在作者一侧定义关系属性,代码如下:

    class Author(db.Model):
        ...
        articles = db.relationship('Article')

  3. 创建表

    # 我在这里是通过python直接创建表,因此使用了app.app_context()这个方法,这个方法主要是用来引入flask的各种方法,否则操作会产生报错
    with app.app_context():
        # 将所有的模型文件创建为表
        db.create_all()
        # 删除数据库中所有的表
        db.drop_all()
  4. 建立关系

    建立关系这里指的是,将两张表的数据进行关系,主要有以下两种方式:外键字段赋值、关系属性赋值。

    这里我们先准备几组数据,用来操作实现关系的建立。

    from market import app,db
    from market.models import Author,Article
    ​
    author1 = Author(name='余华',email='yuhua@euansu.cn')
    author2 = Author(name='莫言',email='moyan@euansu.cn')
    author3 = Author(name='史铁生',email='shitiesheng@euansu.cn')
    ​
    article1 = Article(title='活着',description='活着')
    article2 = Article(title='许三观卖血记',description='许三观卖血记')
    article3 = Article(title='我与地坛',description='我与地坛')
    article4 = Article(title='红高粱',description='红高粱')
    article5 = Article(title='蛙',description='蛙')
    ​
    with app.app_context():
        db.session.add(author1)
        db.session.add(author2)
        db.session.add(author3)
        
        db.session.add(article1)
        db.session.add(article2)
        db.session.add(article3)
        db.session.add(article4)
        db.session.add(article5)
        
        db.session.commit()

    执行如上操作后,查看数据库,正常插入了数据。

    这里需要注意,关系属性虽然在作者模型中,但并未实际在表中创建字段,接下来通过如下代码对数据表中的数据建立一对多关系:

    # 外键字段赋值
    with app.app_context():                              
        author = Author.query.filter_by(name='余华').first() 
        article = Article.query.filter_by(title='活着').first()
        article.author_id = author.id
        db.session.commit()

    执行完成后,查看数据库,数据表 author_id 的值为关联作者的主键值。

    # 执行完外键关系赋值后,可以通过如下调用,查询作者余华关联的图书
    with app.app_context():                              
        author = Author.query.filter_by(name='余华').first() 
        print(author.articles)
    # 操作关系属性
    with app.app_context():                              
        author = Author.query.filter_by(name='余华').first()
        article = Article.query.filter_by(title='许三观卖血记').first()
        author.articles.append(article)
        # 提交事务,将变更写入到数据库
        db.session.commit()

    执行完成后,查看数据库,数据表 author_id 的值为关联作者的主键值。

    # 执行完外键关系赋值后,可以通过如下调用,查询作者余华关联的图书
    with app.app_context():                              
        author = Author.query.filter_by(name='余华').first() 
        print(author.articles)

因此,综上步骤,我们通过Flask建立两个表之间的一对多关系时,需要通过以下三个步骤:

  1. 定义外键,需要在 “多” 侧表的模型中增加外键字段。

  2. 定义关系属性,需要在 “一” 侧表的模型中定义关系属性,该属性并不体现在实际的表中。

  3. 建立关系,通过指定外键字段或操作关系属性,能够建立两个表之间的一对多关系属性。

建立双向关系

我们在 Author 类中定义了集合关系属性 articles ,用以获取某个作者的多个作品。在特殊场景下,也有可能希望在 Article 类中定义一个类似的 author 关系属性,当被调用时,返回关联的 Author 记录,这类返回单个值的关系属性被称为标量关系属性。而两侧都添加关系属性获取对方记录的称之为双向关系

双向关系并不是必须的,只是满足于特殊的场景,可以按照如下方式建立双向关系:

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)
    email = db.Column(db.String(128))
    articles = db.relationship('Article')
​
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), index=True)
    description = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
    author = db.relationship('Author')

使用如下 Python 代码查询:

with app.app_context():
    author = Author.query.filter_by(name='余华').first()
    article = Article.query.filter_by(title='许三观卖血记').first()
    print(author.articles)
    print(article.author)

使用 backref 简化关系定义

backef 参数用来自动为关系另一侧添加关系属性,作为反向引用,赋予的值会作为关系另一侧的关系属性名称。

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)
    email = db.Column(db.String(128))
    articles = db.relationship('Article', backref='author')
​
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), index=True)
    description = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))

再次执行关系属性语句:

with app.app_context():
    author = Author.query.filter_by(name='余华').first()
    article = Article.query.filter_by(title='许三观卖血记').first()
    print(author.articles)
    print(article.author)

能够正常获取其关系的对象。

使用 backref 非常方便,但通常来说 “显式好过隐式”,所以我们应该尽量使用 back_populates 定义双向关系。

多对一

一对多的关系反过来就是多对一,这两种关系模型分别从不同的视角出发。

在一对多中,我们提交以下两点:

  1. 定义外键,需要在 “多” 侧表的模型中增加外键字段。

  2. 定义关系属性,需要在 “一” 侧表的模型中定义关系属性,该属性并不体现在实际的表中。

因此,多对一的关系代码定义如下:

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)
    email = db.Column(db.String(128))
    # 定义外键
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
    # 定义关系属性
    articles = db.relationship('Article')
​
​
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), index=True)
    description = db.Column(db.Text)

一对一

一对一关系是在一对多关系的基础上转化而来,只要确保两侧的关联关系唯一即可保证一对多关系转系转化为了一对一关系,在定义时,设置关系属性的 uselistFlase ,此时的一对多关系转化为一对一关系。

class Person(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(30), unique = True)
    idcard = db.relationship('IDCard', uselist = False)
​
    def __repr__(self):
        return '<Person %r>' % self.name
​
class IDCard(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    idcard = db.Column(db.String(30), unique = True)
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
    person = db.relationship('Person')
​
    def __repr__(self):
        return '<IDCard %r>' % self.idcard

这里执行如下操作先写入数据:

with app.app_context():              
    idcard = IDCard(idcard='123456789')  
    idcard2 = IDCard(idcard='123456798') 
    person = Person(name='euansu')
    db.session.add(idcard) 
    db.session.add(idcard2) 
    db.session.add(person) 
    db.session.commit()

建立关系:

# 指定外键id
with app.app_context():                              
    idcard = IDCard.query.filter_by(idcard='123456789').first() 
    person = Person.query.filter_by(name='euansu').first()
    idcard.person_id = person.id
    db.session.commit()

查看数据库,正常写入:

# 操作关系属性
with app.app_context():                              
    idcard = IDCard.query.filter_by(idcard='123456798').first() 
    person = Person.query.filter_by(name='euansu').first()
    person.idcard.append(idcard)
    # 提交事务,将变更写入到数据库
    db.session.commit()

多对多

多对多关系中,需要建立一个关联表,关联表并不存在数据,只用来存储两侧模型外键的对应关系。

association_table = db.Table(
    'association',
    db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
    db.Column('teacher_id', db.Integer, db.ForeignKey('teacher.id')) 
    ) 
​
class Student(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(128), unique=True) 
    grade = db.Column(db.String(20)) 
    teachers = db.relationship('Teacher', secondary=association_table, back_populates='students') 
​
class Teacher(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(128), unique=True) 
    grade = db.Column(db.String(20))
    stutents = db.relationship('Student', secondary=association_table, back_populates='teachers') 

创建完模型之后,执行迁移,在数据库中查看到新增的三张表:

flask db migrate
​
flask db upgrade

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/484893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实现登录拦截功能

1.4、实现登录拦截功能 温馨小贴士&#xff1a;tomcat的运行原理 当用户发起请求时&#xff0c;会访问我们像tomcat注册的端口&#xff0c;任何程序想要运行&#xff0c;都需要有一个线程对当前端口号进行监听&#xff0c;tomcat也不例外&#xff0c;当监听线程知道用户想要和…

Django之Celery篇(三)

一、任务交给Celery Django任务交给Celery的方法和普通使用Celery任务的调用基本无区别,只是将执行代码的放到到View视图中 而获取结果,往往并不能把结果和第1次请求一起响应,若想获取结果是通过第2次请求获取结果 代码如下: from django.http import HttpResponsefrom …

蓝桥杯2019年第十届省赛真题-组队

一、题目 组队 题目描述 作为篮球队教练&#xff0c;你需要从以下名单中选出 1 号位至 5 号位各一名球员&#xff0c; 组成球队的首发阵容。每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1 号位至 5 号位的评分之和最大可能是多少&#xff1f; &#xff…

nodejs+vue高校社团管理小程序的设计与实现python-flask-django-php

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低学校的运营人员成本&#xff0c;实现了高校社团管理的标准化、制度化、程序化的管理&#xff0c;有效地防止了高校社团管理的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准…

【LVGL-使用GUI Guider 拖拽式设计LVGL】

LVGL-使用GUI Guider 拖拽式设计LVGL ■ SDL2-简介■ PC模拟器&#xff1a;SDL2■ 编译工具链&#xff08;MinGW CMake&#xff09;■ 一个IDE&#xff0c;SDL可以配合以下IDE使用 ■ GUI Guider-简介■ GUI Guider-下载安装■ GUI Guider-使用■ 创建工程■ 切换成中文显示■…

阿里云2核4G服务器优惠价格,轻量165元1年,ECS 199元一年

阿里云2核4G服务器优惠价格&#xff0c;轻量165元1年&#xff0c;ECS 199元一年。2024年腾讯云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0…

Redis技术学习|实战项目记录|商户缓存

学习资料声明 黑马程序员的Redis学习视频&#xff1a;黑马程序员Redis入门到实战教程 需要用到的知识&#xff1a;linux&#xff08;推荐韩顺平老师的教程&#xff0c;学到p30&#xff0c;创建好虚拟机和简单的几个命令就好。&#xff09;SSM。SpringBoot。 还用到了MybatisPl…

SpringBoot+Mysql实现的旅游景点酒店平台系统源码+运行教程+开发文档(参考论文)【猿来入此】优秀学员作品

今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的旅游景点酒店预约管理系统&#xff0c;主要实现了 除脚手架功能以外下面是系统的功能&#xff1a; 前台普通用户&#xff1a;注册、登录、首页、景点列表&#xff08;预约&#xff09;、酒店列表&#…

MySQL-4.数据类型

数据库与编程不太一样&#xff0c;它会更加的珍惜字节空间&#xff0c;需考虑所定义字段的大小和所定义字段的实际使用&#xff08;有无符号&#xff09;。 4.1 数值类型 4.1.1 整型 数据类型字节数无符号数的取值范围有符号数的取值范围TINYINT10~255-128~127SMALLINT20~655…

数学建模体育建模和经济建模国防科大版

目录 6.体育中的数学建模 7.经济学问题中的数学建模 7.1.实物交换模型 7.2.边际效应 7.3.最佳消费选择模型 6.体育中的数学建模 体育科学的研究中&#xff0c;也有大量的数学建模问题&#xff0c;例如&#xff1a;棒球的最佳击球点问题、滑板滑雪赛道的设计、越野自行车比…

基于Google云原生工程师的kubernetes最佳实践(三)

目录 三、集群管理 利用node affinity、taint等机制管理node 通过pod affinity/anti-affinity机制将pod分配到合适的node Node分级管理 从Qos角度将Pod分级 用namespace隔离不同的环境和用户 配置RBAC权限控制 1. 遵循最小权限原则 2. 使用 Role 和 ClusterRole 分离权…

STM32使用滴答定时器实现delayms

在STM32上使用SysTick实现jiffies&#xff08;时间戳&#xff09;并且实现delay_ms 代码实现&#xff1a; volatile uint32_t jiffies 0; // 用于记录系统运行的jiffies数 void SysTick_Handler(void) {/* 每次SysTick中断&#xff0c;jiffies增加 */jiffies; }uint32_t tick…

matlab 智能电器的状态监测故障模拟

1、内容简介 略 83-可以交流、咨询、答疑 2、内容说明 略 U120√2sin(2) Ii1i2 逻辑关系&#xff1a; 在0-0.1&#xff0c;正弦电给并联的电容和电阻/电感供电&#xff0c;电压的有效值为120V,通过RMS模块检查电压的变化&#xff0c;在0.1时通过斩波器把电源2端与大地连接…

苹果CMS影视APP源码,二开版本带视频教程

编译app教程 工具下载&#xff1a;Android Studio 官网地址&#xff1a;https://developer.android.google.cn/studio/ 环境设置&#xff1a; 设置中文&#xff1a;https://blog.csdn.net/qq_37131111/article/details/131492844 汉化包找最新的下载就行了&#xff0c;随便下载…

SpringJPA 做分页条件查询

前言: 相信小伙伴们的项目很多都用到SpringJPA框架的吧,对于单表的增删改查利用jpa是很方便的,但是对于条件查询并且分页 是不是很多小伙伴不经常写到. 今天我整理了一下在这里分享一下. 话不多说直接上代码: Controller: RestController public class ProductInstanceContr…

idea maven配置

修改maven的路径&#xff08;使用本地的Maven&#xff09;&#xff0c;以及修改settings文件的位置和本地仓库的位置。 -DarchetypeCataloginternal 配置阿里云镜像&#xff08;在setting.xml文件中配置&#xff09; <!-- 配置阿里云 --> <mirror> <id>…

【PHP + 代码审计】数组排序算法

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

需求:实现一个类似打印的效果(文字一个字一个字的输出)

实现效果&#xff1a; 需求&#xff1a;最近接到这么一个需求&#xff0c;ai机器人回复的问题&#xff0c;后端是通过websocket每隔一段事件返回数据&#xff0c;前端拿到数据后直接渲染&#xff0c;现在需要做到一个效果&#xff0c;后端返回的结果前端需要一个一个文字的输出…

STM32微控制器的中断优先级设置中,抢占优先级和子优先级如何影响中断响应?

在STM32微控制器中&#xff0c;中断优先级设置是一个关键的概念&#xff0c;它决定了在发生多个中断时&#xff0c;哪些中断能够优先被处理。STM32的中断优先级系统包括抢占优先级&#xff08;Preemption Priority&#xff09;和子优先级&#xff08;Subpriority&#xff09;&a…

P - Beat

题目分析 1.看数据范围&#xff0c;大概知道dfs能做 2.自0问题开始查找&#xff0c;确保之后每次查找到的问题的困难度均大于上一次 3.遍历所有情况再记录cnt即可 代码 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring&…