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

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

前言

    在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())
相关文章
|
7月前
|
存储 缓存 NoSQL
深入理解Django与Redis的集成实践
深入理解Django与Redis的集成实践
180 0
|
4月前
|
SQL 安全 数据库
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
298 77
|
4月前
|
SQL 安全 数据库连接
除了使用Django的ORM,还能通过什么方式在Django中避免SQL注入漏洞?
除了使用Django的ORM,还能通过什么方式在Django中避免SQL注入漏洞?
156 73
|
5月前
|
SQL 定位技术 数据库
深入探索Django ORM:高效数据库操作的秘诀####
本文旨在为读者揭开Django ORM(对象关系映射)的神秘面纱,通过一系列生动的比喻和详实的案例,深入浅出地讲解其核心概念、工作原理及高级特性。我们将一起探讨如何利用Django ORM简化数据库交互,提升开发效率,同时确保数据的一致性和安全性。不同于传统的技术文档,本文将以故事化的形式,带领读者在轻松愉快的氛围中掌握Django ORM的精髓。 ####
|
6月前
|
SQL 监控 数据库
深入探索Django ORM:高效数据操作的秘诀与实践####
在当今的Web开发领域,提升数据访问层的效率是优化应用性能的关键。本文旨在通过剖析Django框架中的ORM(对象关系映射)机制,揭示其如何简化数据库交互,并探讨一系列高级技巧与策略,帮助开发者构建更高效、可维护的数据访问代码。我们不涉及安装步骤或基础概念,而是聚焦于实战经验分享,旨在为中高级开发者提供深度洞见。 ####
|
7月前
|
数据库 数据安全/隐私保护 数据库管理
#765372#基于django和neo4j的通用数据展示系统
#765372#基于django和neo4j的通用数据展示系统
73 1
|
7月前
|
SQL Go 数据库
【速存】深入理解Django ORM:编写高效的数据库查询
【速存】深入理解Django ORM:编写高效的数据库查询
175 0
|
6月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
427 45
|
8月前
|
机器学习/深度学习 人工智能 算法
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
植物病害识别系统。本系统使用Python作为主要编程语言,通过收集水稻常见的四种叶片病害图片('细菌性叶枯病', '稻瘟病', '褐斑病', '稻瘟条纹病毒病')作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算法模型,并进行多轮迭代训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地模型文件。再使用Django搭建Web网页平台操作界面,实现用户上传一张测试图片识别其名称。
270 22
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
|
6月前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
210 2