前言
在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 DELETE
和 ON 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
来进行关系的断开而不是直接使用
delete
,remove
只会断开数据之间的联系,但是不会将数据删除
# 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())