什么是关系映射?

  • 在关系型数据库中,通常不会把所有数据都放在同一张表中,不易于扩展。

常见的关系映射

  • 一对一映射:例如一个身份证对应一个人

  • 一对多映射:例如一个班级可以有多个学生

  • 一对多映射:例如一个学生可以报考多个课程,一个课程可由多个学生学习.

一对一映射(创建)


  • 一对一是表示现实事物间存在的一对一的对应关系。

  • 语法: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')

反向查询

  • 没有外键属性的一方,可以调用反向属性查询到关联的另一方

  • 反向关联的属性为实例对象.引用类名(小写)

  • 当反向引用不存在的时候,则会触发异常

当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类对象


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)

一对多映射(创建数据)

有两种方法创建数据,跟上面一对一的一样


class1 = ClassRoom.objects.create(name="高二三班")

Students.objects.create(student_name="XiaoMing",classroom=class1) # 对应外键的属性名,必须传入class对象

Students.objects.create(student_name="Liyang",classroom_id=1) # 对应外键值属性字段,必须传入具体的值

一对多(查询数据)


正向查询


Students.classroom # 直接通过调用外键属性查询

stu = Students.objects.get(id=1)

print(stu.student_name,"的班级是",stu.classroom.name)

XiaoMing 的班级是 高二三班

反向查询[通过ClassRoom查询所有Student]


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:先创建班级,在关联老师


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)