什么是关系映射?
- 在关系型数据库中,通常不会把所有数据都放在同一张表中,不易于扩展。
常见的关系映射
- 一对一映射:例如一个身份证对应一个人
- 一对多映射:例如一个班级可以有多个学生
- 一对多映射:例如一个学生可以报考多个课程,一个课程可由多个学生学习.
一对一映射(创建)
- 一对一是表示现实事物间存在的一对一的对应关系。
- 语法:
OneToOneField(类名,on_delete=xxx)
class Asset (models.Model):
create_date = models.DateTimeField(verbose_name="创建日期",auto_now=True)
class User(models.Model)
a = models.OneToOneField(Asset,on_delete=1) # on_delete是级联删除的动作
级联删除
级联删除,例如员工表中一项数据是部门ID,部门ID是部门表的主键,如果是级联删除,当删除了部门A的时候,会把所有属于部门A的员工都给删除。
- 级联删除的特殊字段
models.CASCADE
:Django模拟SQL约束ON DELETE CASCADE,并删除包含ForeignKey的对象
注意该CASCADE会有限查找是否有关联数据,先删除管理数据,再删除本条数据.
models.PROTECT
:抛出ProtectedError以阻止被引用对象的删除SET_NULL
:设置ForeignKey为Null,需要指定null=True
from django.db import models
import uuid
# Create your models here.
class UserMit(models.Model):
# id创建为UUID类型,字段命名为user_id
id = models.UUIDField(primary_key=True,default=uuid.uuid4,db_column='user_id')
name = models.CharField(verbose_name="User_name",max_length=20,default="")
class UserId(models.Model):
name = models.CharField(verbose_name="Test",max_length=15)
users = models.OneToOneField(UserMit,on_delete=models.CASCADE) # 一对一即users_id 对应 id
一对一映射(创建数据)
- 无外键约束的模型类
UserMit
# 进入Django Shell操作
create1 = UserMit.objects.create(name="henan)
- 有外键约束的模型类
UserId
create2 = UserId.objects.create(name="henan",users=create1) # 通过关联UserMit的实例化对象
create4 = UserId.objects.create(uid="henan",users_id="0dbccd1992474d30a4497b05295e807b") # 关联UserMit表中的user_id对应主键
一对一(查询数据)
正向查询
- 正向查询:直接通过外键属性查询,则为外键查询
# 通过外键绑定的users_id查询用户,接着上面的创建数据来
>>> a2.id
6
>>> a2.users_id
UUID('43ff679f-42b2-4334-85a0-b493503d6433')
反向查询
- 没有外键属性的一方,可以调用反向属性查询到关联的另一方
- 反向关联的属性为
实例对象.引用类名(小写)
- 当反向引用不存在的时候,则会触发异常
代码语言:javascript复制当UserId类中定义了外键约束,则UserMit类中会有一个UserId的反向属性
class UserMit(models.Model):
id = models.UUIDField(primary_key=True,default=uuid.uuid4,db_column='user_id')
name = models.CharField(verbose_name="User_name",max_length=20,default="")
class UserId(models.Model):
name = models.CharField(verbose_name="Test",max_length=15)
users = models.OneToOneField(UserMit,on_delete=models.CASCADE)
>>> select1 = UserMit.objects.get(name='wlx')
>>> select1.userid.users_id
UUID('c443d1b4-0882-42cb-8659-86ccbd1f8d12')
一对多的映射
一对多是表现现实事物存在的一对多的对应关系,例如一个学校有多个班级,一个班级有多个学生,一本书只能属于一个出版社,一个出版社可以出多本书。
一对多需要明确出具体角色,在多表上设置外键
语法:当一个A类对象可以关联多个B类对象
代码语言:javascript复制class ClassRoom(models.Model):
# 班级唯一
name = models.CharField("ClassName",max_length=50,unique=True)
class Students(models.Model):
# 学生多个,可以多个学生在一个班
student_name = models.CharField("StudentName",max_length=15)
# 绑定外键约束,属于那个班级
classroom = models.ForeignKey(ClassRoom,on_delete=models.CASCADE)
一对多映射(创建数据)
代码语言:javascript复制有两种方法创建数据,跟上面一对一的一样
class1 = ClassRoom.objects.create(name="高二三班")
Students.objects.create(student_name="XiaoMing",classroom=class1) # 对应外键的属性名,必须传入class对象
Students.objects.create(student_name="Liyang",classroom_id=1) # 对应外键值属性字段,必须传入具体的值
一对多(查询数据)
正向查询
代码语言:javascript复制Students.classroom # 直接通过调用外键属性查询
stu = Students.objects.get(id=1)
print(stu.student_name,"的班级是",stu.classroom.name)
XiaoMing 的班级是 高二三班
反向查询[通过ClassRoom查询所有Student]
代码语言:javascript复制class1 = ClassRoom.objects.get(name="高二三班")
stu1 = class1.students_set.all() # students_set 是独有的反向属性,获取多个数据,是关联外键的类名小写
for i in stu1:
print(i.id,i.student_name,i.classroom_id)
多对多映射
多对多表达对象之间多对多的复杂关系,如:每个人都有不同的学校,每个学校都有不同的学生
- MySQL中创建多对多需要以来第三张表来完成
- Django中无需手动创建,Django自动完成
- 语法:在关联的两个类中的任意一个类中
models.ManyToManyField(MyModel)
张老师和王老师同时带领高二三班,李老师和王老师都都参与过高三班的课
class ClassRoom(models.Model):
# 班级唯一
name = models.CharField("ClassName",max_length=50,unique=True)
class Students(models.Model):
# 学生多个,可以多个学生在一个班
student_name = models.CharField("StudentName",max_length=15)
# 绑定外键约束,属于那个班级
classroom = models.ForeignKey(ClassRoom,on_delete=models.CASCADE)
class Teacher(models.Model):
# 教师
teacher_name = models.CharField("TeacherName",max_length=20,default="")
name = models.ManyToManyField(ClassRoom)
多对多(创建数据)
方案1:先创建班级,在关联老师
代码语言:javascript复制class1 = ClassRoom.objects.create(name="高三九班")
# 张老师和王老师同时带领高二三班
b1 = class1.teacher_set.create(teacher_name="张老师")
b2 = class1.teacher_set.create(teacher_name="王老师")
# 或者
class1.teacher_set.add(b1)
class1.teacher_set.add(b2)