Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践

在这里插入图片描述

系列文章目录

  • Django入门全攻略:从零搭建你的第一个Web项目
  • Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作
  • Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
  • Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践
  • 还在写0.0…

文章目录

  • 系列文章目录
  • 前言
  • 一、多对一关系
    • 1.多对一关系是什么
    • 2.多对一关系的增删改操作
    • 3.多对一的正向查询
    • 4.多对一的反向查询
  • 二、一对一关系
    • 1.一对一关系是什么
    • 2.一对一关系的增删改操作
    • 3.一对一关系正向查询
    • 4.一对一关系反向查询
  • 三、多对多关系
    • 1.多对多关系是什么
    • 2.多对多关系的外键添加操作
    • 3.多对多关系的外键移除工作
    • 4.多对多关系的修改和查询


前言

    在Django开发中,数据关系的管理至关重要。今天,我们将快速了解Django ORM如何处理多对一、一对一和多对多这三种核心数据关系。这些基础知识将帮助你更高效地构建数据库驱动的应用。让我们一起探索Django ORM的奥秘吧!


一、多对一关系

1.多对一关系是什么

Django使用django.db.models.ForeignKey定义多对一关系。

博客表—用户表 - - - 多对一

# app/model.py
class UserModel(models.Model):
    name = models.CharField(max_length=50)
    age = models.IntegerField()
    height = models.DecimalField(max_digits=3, decimal_places=2)
    def __str__(self):
        return self.name
    class Meta:
        db_table = 'users'


class BlogModel(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateField()
    address = models.CharField(max_length=50)
    user = models.ForeignKey(to=UserModel, on_delete=models.CASCADE)
    def __str__(self):
        return self.title
    class Meta:
        db_table = 'blogs'

2.多对一关系的增删改操作

增:

    # 1.添加user
    u1 = UserModel.objects.create(name="王五", age=18, height=1.78)

    # 2.为 id(pk) = 1的用户添加blog
    u2 = UserModel.objects.get(pk=1)
    blog = BlogModel()
    blog.title = "ORM关联模型"
    blog.content = "多对一、一对一、多对多模型"
    blog.pub_date = "2024-05-31"
    blog.address = "csdn"
    blog.user = u2
    blog.save()

改:

    # 1.修改用户信息
    # u3 = UserModel.objects.get(id=1)
    # u3.age = 100
    # u3.save()
    # 2.修改博客信息
    # b3 = BlogModel.objects.get(id=9)
    # b3.address = "修改后的CSDN地址"
    b3 = BlogModel.objects.filter(id=9).update(address="再修改(update)后的CSDN地址")

    # b3.save()

删:

    # 1.删除blog表中的记录,直接删除
    # blog = BlogModel.objects.get(pk=10)
    # blog.delete()
    # 2.删除user表中数据,此user对应的blog也会删除
    u4 = UserModel.objects.get(pk=2)
    u4.delete()

3.多对一的正向查询

	# 多查询一的情况下,直接通过模型类中的外键关联字段查询
    # 正向查询
    b5 = BlogModel.objects.get(user_id=1)
    print(b5)
    print(b5.user.name)
    print(b5.user.age)
    print(b5.user.height)
>>>ORM关联模型
>>>张安
>>>100
>>>1.96  

4.多对一的反向查询

    # 反向查询:主表通过blogmodel_set查从表
    u6 = UserModel.objects.get(id=1)
    print(u6)
    b6 = u6.blogmodel_set.all()
    print(b6)
    for blog in b6:
        print(blog.title)
        print(blog.content)

二、一对一关系

1.一对一关系是什么

模型类使用OneToOneField用来定义一对一关系;

学生表与学生信息表 - - - 一对一
models.CASCADE:多表关联, 删除数据的时候 一删就全删

#app/model.py
class StudentModel(models.Model):
    name = models.CharField(max_length=50)
    age = models.IntegerField()
    height = models.DecimalField(max_digits=3, decimal_places=2)
    def __str__(self):
        return self.name
    class Meta:
        db_table = 'students'


class StuDetail(models.Model):
    address = models.CharField(max_length=50)
    idcard = models.CharField(max_length=50)
    outlook = models.CharField(max_length=50)
    student = models.OneToOneField(to=StudentModel, on_delete=models.CASCADE)
    def __str__(self):
        return self.idcard
    class Meta:
        db_table = 'detail'

其中,ON DELETEON UPDATE 表示事件触发限制,各参数意义如下:

参数意义
RESTRICT限制外表中的外键改动(默认值,也是最安全的设置)
CASCADE跟随外键改动
SET NULL设为null值
NO ACTION无动作
SET DEFAULT设为默认值

2.一对一关系的增删改操作

增:

    # 1.增加学生 Student
     st1 = StudentModel()
     st1.name = "张三三"
     st1.age = 18
     st1.height = 1.79
     st1.save()

    # 2.增加学生信息 StuDetail
     sd1 = StuDetail()
     sd1.address = "北京"
     sd1.idcard = 123
     sd1.outlook = '团员'
     sd1.student = st1
     sd1.save()

改:

    # 3.修改 学生详细信息
    sd2 = StuDetail.objects.get(id=1)
    sd2.address = "我在中东吃炸鸡"
    sd2.save()

    # 4.修改 学生信息
    st2 = StudentModel.objects.get(id=1)
    st2.age = 12
    st2.save()

删:

    # 5.删除
     st5 = StudentModel.objects.get(id=1)
     st5.delete()

3.一对一关系正向查询

    # 5.正向查询:
    sd3 = StuDetail.objects.get(id=1)
    print(sd3.address)
    print(sd3.idcard)
    print(sd3.outlook)
    print(sd3.student.name)
    print(sd3.student.age)

4.一对一关系反向查询

	# 6.反向查询:
    st4 = StudentModel.objects.get(id=1)
    print(st4.name)
    print(st4.age)
    print(st4.studetail.address)
    print(st4.studetail.idcard)
    print(st4.studetail.outlook)
    
    #print(stu.blogmodel_set.all())
    #注意:这是错误的,一对一没有_set,且全通过小写字段(eg:studetail,blogmodel_set)找到类名
	 

三、多对多关系

1.多对多关系是什么

多对多关系在模型中使用ManyToManyField字段定义

多对多关系可以是具有关联,也可以是没有关联,所以不需要明确指定on_delete属性
原因:在多对多的情况,有专门的第三张表,存储 对应关系, 表本身并没有字段来存储对应关系,此时删除任意数据,不影响另一张表数据

电影表与演员表 - - - 多对多

# app/models.py
class ActorModel(models.Model):
    name = models.CharField(max_length=50)
    age = models.IntegerField()
    gender = models.CharField(max_length=2)
    def __str__(self):
        return self.name
    class Meta:
        db_table = 'actors'


class MovieModel(models.Model):
    name = models.CharField(max_length=50)
    mtime = models.CharField(max_length=50)
    info = models.CharField(max_length=50)
    actors = models.ManyToManyField(to=ActorModel)
    def __str__(self):
        return self.name
    class Meta:
        db_table = 'movies'

2.多对多关系的外键添加操作

创建:

    # 1.添加演员
    a1 = ActorModel()
    a1.name = '刘海柱'
    a1.age = 32
    a1.gender = '男'
    a1.save()
    #
    a2 = ActorModel()
    a2.name = '赵小刀'
    a2.age = 30
    a2.gender = '女'
    a2.save()
    #
    a3 = ActorModel()
    a3.name = '哈士奇'
    a3.age = 33
    a3.gender = '男'
    a3.save()
  -------------------------------------------
    # 2.添加电影信息
    m1 = MovieModel()
    m1.name = "精武门"
    m1.mtime = "2h"
    m1.info = "这是一个武打片"
    m1.save()

    m2 = MovieModel()
    m2.name = "ye邪不压正"
    m2.mtime = "2h30min"
    m2.info = "这肯呢个肯呢个可能是一个武打片"
    m2.save()

    m3 = MovieModel()
    m3.name = "don东北黑道纷纭"
    m3.mtime = "2h50min"
    m3.info = "黄及哦啊哦写"
    m3.save()

增加:

	# 3.给电影添加演员--正向的
    a1 = ActorModel.objects.get(id=1)
    a2 = ActorModel.objects.get(id=2)
    a3 = ActorModel.objects.get(id=3)
    # 给任意一个电影添加对应的演员
    m1 = MovieModel.objects.get(id=1)
    m1.actors.add(a1)
    m1.actors.add(a2)
    m1.actors.add(a3)
---------------------------------------------
    # 4.给演员安排几个电影拍
    m2 = MovieModel.objects.get(id=2)
    m3 = MovieModel.objects.get(id=3)
    
    a1 = ActorModel.objects.get(id=1)
    a1.moviemodel_set.add(m2,m3)

3.多对多关系的外键移除工作

多对多关联字段的删除,要使用remove来进行关系的断开
而不是直接使用deleteremove只会断开数据之间的联系,但是不会将数据删除

    # 5.删除,会删除电影及电影-演员表中的对应关系
    # MovieModel.objects.get(id=1).delete()

    # 6.删除对应关系:从某电影m6中移除某演员a1,只影响演员-电影对应关系表
    m6 = MovieModel.objects.get(id=6)
    a1 = ActorModel.objects.get(id=1)
    a1.moviemodel_set.remove(m6)

4.多对多关系的修改和查询

    # 7.查询数据
    # 根据任意一个电影,查询所有参演的演员-
    m1 = MovieModel.objects.get(id=1)
    print("-"*10)
    print(m1.actors.all())
    
    # 根据任意一个演员,查询拍过的所有电影 f反向查询
    a1 = ActorModel.objects.get(id=1)
    print("-"*10)
    print(a1.moviemodel_set.all())

在这里插入图片描述

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

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

相关文章

Java集合进阶——不可变集合

1.概念 不可变集合就是定义完成之后不可以进行修改,添加,删除等操作的集合 2.创建不可变集合的书写格式 在List,Set,Map接口中都存在静态的of方法,可以获取一个不可变的集合 ⑴List的不可变集合 如图:创建的不可变集…

OJ1230进制的转换

答案&#xff1a; #include <bits/stdc.h> using namespace std; using lllong long; const int N10; int a[10]; char ch[]{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}; void solve() {int n,m;cin>>n>>m;string str;cin>>str;for(int i0;i<str.size();i)…

vue:实现丝滑上传进度条

一、效果展示 缓若江海凝清光 . 二、代码 const uploadProgress ref(); //上传进度//进度丝滑更新 //进度&#xff0c;时常 const ProgressChange (targetPercent: number, duration: number) > {//performance.now() 是浏览器提供的一个高性能时间 API&#xff0c;它返…

学习数据分析思维的共鸣

在这篇文章中&#xff0c;我将分享自己在成长过程中对数据分析思维的领悟&#xff0c;从《数据分析思维-产品经理的成长笔记》这本书引发的共鸣&#xff0c;到数据分析在不同岗位的广泛应用&#xff0c;再到如何将学习与快乐联系起来&#xff0c;以及沟通在数据分析中的重要性。…

4.基础纹理

纹理的目的&#xff1a;使用一张图片来控制模型的外观纹理映射技术&#xff1a;把一张图“黏”在模型表面&#xff0c;逐纹素&#xff08;与像素不同&#xff09;地控制模型颜色通常在建模软件中利用纹理展开技术实现&#xff0c;把纹理映射坐标存储在每个顶点上纹理映射坐标&a…

Java线程几种常用方法详细说明

在Java编程中&#xff0c;多线程编程是一个非常重要的主题。它允许我们同时运行多个任务&#xff0c;提高程序的性能和响应速度。在这篇博客中&#xff0c;我们将介绍一些常用的Java线程方法和构造器&#xff0c;并通过示例代码展示如何使用它们。 Thread提供的常用方法 publi…

Python | Leetcode Python题解之第128题最长连续序列

题目&#xff1a; 题解&#xff1a; class Solution:def longestConsecutive(self, nums: List[int]) -> int:longest_streak 0num_set set(nums)for num in num_set:if num - 1 not in num_set:current_num numcurrent_streak 1while current_num 1 in num_set:curre…

GDPU unity游戏开发 动画状态机

每一个动画状态都演绎着你的奔赴。 动画混合 1) 前往 Mixamo选择适合的角色模型和idle/walking/backward动画并下载。确保下载时选择FBX for Unity格式。 2) 新建Unity项目&#xff0c;导入下载的模型。 3) 在导入模型的Inspector窗口中&#xff0c;选择Materials选项卡&a…

美国前总统特朗普竟然入驻TikTok,粉丝破24万

大家好&#xff01; 我是老洪&#xff01; 刚看到一则关于美国前总统特朗普的新闻&#xff0c; 特朗普竟然入驻TikTok了&#xff0c;太令人惊讶了。&#xff08;为什么惊讶&#xff0c;后面再说&#xff09; 更为惊人的是&#xff0c;他的到来竟然引来了众多粉丝的热烈追捧&…

高斯混合模型聚类算法的实现

目录 1. 作者介绍2. 聚类简介2.1 K-Means聚类简介2.2 高斯混合聚类简介 3. 实验过程3.1 数据集介绍3.2 代码思路3.3 算法评价3.4 代码实现3.5 实验结果 4. 参考链接 1. 作者介绍 赵子仪&#xff0c;女&#xff0c;西安工程大学电子信息学院&#xff0c;2023级研究生 研究方向&…

STM32(十):SPI (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中USART通信协议来串口通信&#xff0c;并向XCOM串口助手发送信息。这篇文章我们来介绍一下如何用STM32单片机中SPI接口来实现LED的闪亮并玩转WS2812B灯带。 一、实验原理 串行通信之前的博客里有所介绍&#xff0c;可以查看以下…

回退背包专题

P4141 消失之物 题目意思&#xff0c;就是说有n个物品&#xff0c;然后每个物品都有自己的体积w[i]&#xff0c;然后问你&#xff0c;如果第i个物品丢了之后&#xff0c;还能够装满这个背包的方法&#xff0c;然后遍历一遍i同时也要遍历一遍背包&#xff0c;因为背包的值是在1到…

python数据分析——datetime数据类型2

参考资料&#xff1a;活用pandas库 # 导入pandas库 import pandas as pd # 加载数据集 teslapd.read_csv(r"...\data\tesla_stock_yahoo.csv") # 查看数据 print(tesla.head()) 1、基于日期取数据子集 # 将Date数据列转换为datetime类型 tesla[Date]pd.to_datetime…

【Linux 网络编程】OSI 七层模型初识、网络传输的流程、IP地址和MAC地址!

文章目录 1. OSI七层模型2. TCP/IP五层(或四层)模型3. 网络传输基本流程 &#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#…

Golang | Leetcode Golang题解之第127题单词接龙

题目&#xff1a; 题解&#xff1a; func ladderLength(beginWord string, endWord string, wordList []string) int {wordId : map[string]int{}graph : [][]int{}addWord : func(word string) int {id, has : wordId[word]if !has {id len(wordId)wordId[word] idgraph a…

Flink系列三:Flink架构、独立集群搭建及Flink on YARN模式详解

一、Flink架构 Flink 是一个分布式系统&#xff0c;需要有效分配和管理计算资源才能执行流应用程序。它集成了所有常见的集群资源管理器&#xff0c;例如Hadoop yarn&#xff0c;但也可以设置作为独立集群甚至库运行。 Flink 集群剖析 Flink 运行时由两种类型的进程组成&…

数据分析常用模型合集(一)AARRR模型和漏斗模型

准备把常用的数据分析模型&#xff0c;像什么AARRR&#xff0c;RFM之类的&#xff0c;逐个全部写一下&#xff1b; 最好能带点案例和代码&#xff0c;搞一个小合集。 最终达到完全不懂的人&#xff0c;看完就能知道得差不多&#xff1b; 数据分析常用模型合集&#xff08;二…

TiDB-从0到1-分布式存储

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCC 一、TiDB-DML语句执行流程&#xff08;增删改&#xff09; DML流程概要 1、协议验证 用户连接到TiDB Server后首先工作的是Protocol Layer模块&#xff0c;该模块会对用…

FuTalk设计周刊-Vol.046

# AI漫谈 热点捕手 1、Stable Diffusion 可以生成透明的 PNG 图片了 用 SD 直接生成透明的 PNG 图片&#xff0c;也可以直接生成带有透明度分层的图片&#xff0c;LayerDiffusion 使得大型已经过预训练的潜在扩散模型&#xff08;latent diffusion model&#xff09;能够创造…

docker学习--最详细的docker run 各子命令解释与应用

文章目录 docker run应用docker run -it那怎样才能退出容器而不用容器关闭呢 docker run -d-p-P--name docker run 容器运行命令 docker run 常见的子命令及其含义 -i 交互式&#xff0c;和-t一起使用 -t 打开一个终端 -d 后台运行 -p/-P 暴露容器中的服务端口 –name 指定容…