使用on_delete指定级联删除策略:
CASCADE:当父表数据删除时,相对应的从表数据会被自动删除
SET_NULL:当父表数据删除时,相对应的从表数据会被自动设置为null值
PROTECT:当父表数据删除时,如果有相对应的从表数据会抛出异常
SET_DEFAULT: 当父表数据删除时,相对应的从表数据会被自动设置为默认值,还需要额外指定default=True
举例:一个人对应一个身份证号
数据字段设置 unique
可以在任何一个模型类使用OneToOneField
举例:一个学生有多个老师,一个老师有多个学生
一般通过第三个表来实现关联
可以在任何一个模型类使用ManyToManyField
创建学生与地址表(学生是一,地址是多)
class Student(models.Model):
# 模型类中不需要指定 id字段,会自动生成
# 数据库的可变字符串类型 varchar(20)
name = models.CharField(max_length=20)
age = models.IntegerField()
create_time = models.DateTimeField('创建时间')
class Address(models.Model):
# CASCADE:当父表数据删除时,相对应的从表数据会被自动删除
student = models.ForeignKey(Student, on_delete=models.CASCADE)
detail = models.CharField(max_length=200)
增
需求:增加一个叫王老五的学生,给王老五添加一个地址
# 一对多,多对一 新增
def foreignkey_add(request):
# 增加学生,和单表一样,采用 create方法直接生成数据,不需要再去调用save
student = Student.objects.create(name='王老五', age=10,create_time=timezone.now())
# 增加地址,通过外键_id形式给外键赋值 id
Address.objects.create(detail="河北省", student_id=student.id)
return HttpResponse("一对多,新增成功!!!")
删
需求:删除id=2的学生,同时删除该学生对应的地址
# 一对多,多对一 删除
def foreignkey_del(request):
# 删除学生(因创建表的时候,两表定义的关系为:on_delete=models.CASCADE ,所以删除学生,其对应的地址也会被删除)
Student.objects.filter(id=2).delete()
return HttpResponse("一对多,删除成功!!!")
改
需求:修改id=4的学生,修改id=3的地址
# 一对多,多对一 修改
def foreignkey_update(request):
# 修改学生
Student.objects.filter(id=4).update(name="小明")
# 修改地址(修改需要用 filter 获取地址的查询集,使用 get 报错)
Address.objects.filter(id=3).update(detail='武汉市')
return HttpResponse("一对多,修改成功!!!")
正向查询: 先查询学生,再通过学生查询出其地址
反向查询: 先查询地址,再通过地址查询出学生
# 一对多,多对一 查询
def foreignkey_query(request):
# 正向查询:通过学生,查询学生对应的地址信息
# 查询id为2 的学生 以及他对应的地址信息
# 1. 查询学生对象
student = Student.objects.get(id=2)
# 2. # 通过django内置的属性 模型类_set, 可以查询出学生下的所有地址
addressSet = student.address_set.all()
res='正向查询:该学生所有的地址是:
'
# 遍历所有对象
for q in addressSet:
res += str(q.id) + "." + q.detail + "
"
res = '反向查询:地址对应的学生是:
'
# 反向查询:通过地址,查询对应学生
# 查询id为3的地址,以及对应的学生
# 1. 查询地址对象
address = Address.objects.get(id=3)
# 2. 获取对应的学生信息 (对象.外键.关联模型类的字段)
studentName = address.student.name
res +=studentName+ "
"
return HttpResponse(res)
创建学生与身份证信息表(学生是一,身份证是一)
class Student(models.Model):
# 模型类中不需要指定 id字段,会自动生成
# 数据库的可变字符串类型 varchar(20)
name = models.CharField(max_length=20)
age = models.IntegerField()
create_time = models.DateTimeField('创建时间')
class Idcard(models.Model):
remark = models.CharField(max_length=200,verbose_name="备注")
num=models.CharField(max_length=20,verbose_name="身份证号")
# CASCADE:当父表数据删除时,相对应的从表数据会被自动删除
student = models.OneToOneField(to=Student, on_delete=models.CASCADE)
注:学生表之前就有,本次只需要新增 Idcard 表即可,添加完模型后,再次执行迁移命令:
# 重新生成迁移文件
python manage.py makemigrations score
# 同步数据库
python manage.py migrate
增
# 一对一 新增
def oneToone_add(request):
# 增加学生
student = Student.objects.create(name='小王', age=14,create_time=timezone.now())
# 增加身份信息
Idcard.objects.create(num="123456789",remark="这是身份证", student_id=student.id)
return HttpResponse("一对一,新增成功!!!")
删
# 一对一 删除
def oneToone_del(request):
# 删除学生(其对应的身份信息也会被删除)
Student.objects.filter(id=5).delete()
# 删除身份信息(学生不会被删除)
# Idcard.objects.filter(id=1).delete()
return HttpResponse("一对一,删除成功!!!")
改
# 一对一 修改
def oneToone_update(request):
# 修改学生
Student.objects.filter(id=2).update(name="小王王")
# 修改身份
Idcard.objects.filter(id=2).update(remark='这是护照')
return HttpResponse("一对一,修改成功!!!")
查
# 一对一 查询
def oneToone_query(request):
# 正向查询:通过学生,查询学生对应的身份信息
student = Student.objects.get(id=6)
idcard_num = student.idcard.num
res='正向查询:该学生所有的身份id是:
'+idcard_num+"
"
# 反向查询:通过身份,查询对应学生
idcard = Idcard.objects.get(id=2)
student_name = idcard.student.name
res +='反向查询:身份对应的学生是:
'+student_name+ "
"
return HttpResponse(res)
创建学生与老师表(一个学生对应多个老师,一个老师对应多个学生)
class Student(models.Model):
# 模型类中不需要指定 id字段,会自动生成
# 数据库的可变字符串类型 varchar(20)
name = models.CharField(max_length=20)
age = models.IntegerField()
create_time = models.DateTimeField('创建时间')
class Teacher(models.Model):
name = models.CharField(max_length=20)
gender = models.IntegerField(choices=((0,"男"),(1,"女")),verbose_name='性别')
# 多对多没有 on_delete参数
# 在多对多的情况,有专门的第三张表,存储 对应关系,表本身并没有字段来存储对应关系,此时删除任意数据,不影响另一张表数据
student = models.ManyToManyField(to=Student)
执行完迁移命令后,出现以下表:
增
# 多对多 新增
def manyTomany_add(request):
# 增加老师
teacher = Teacher.objects.create(name='王老师', gender=1)
# 增加学生
student = Student.objects.create(name='小三', age=20,create_time=timezone.now())
# 给老师添加多个学生
# 对象.关联字段.add(关联的student表的id)
teacher.student.add(2,3)
return HttpResponse("多对多,新增成功!!!")
删
# 多对多 删除
def manyTomany_del(request):
# 多对多关联字段的删除,要使用 remove 来进行关系的断开,而不是直接使用 delete
# remove 只会断开数据之间的联系,但是不会将数据删除
teacher = Teacher.objects.get(id=1)
student = Student.objects.get(id=2)
# 老师对象.关联字段.remove(学生对象)
teacher.student.remove(student)
return HttpResponse("多对多,删除成功!!!")
改
先解除原有关联,再重新添加新的关系
查
# 多对多 查询
def manyTomany_query(request):
# 正向查询:通过学生,查询学生对应的老师
student = Student.objects.get(id=3)
teacher_list = student.teacher_set.all()
res = '正向查询:该学生的老师是:
'
# 遍历所有对象
for q in teacher_list:
res += str(q.id) + "." + q.name + "
"
# 反向查询:通过老师,查询对应学生
teacher = Teacher.objects.get(id=1)
student_list = teacher.student.all()
res += '反向查询:老师对应的所有学生是:
'
# 遍历所有对象
for q in student_list:
res += str(q.id) + "." + q.name + "
"
return HttpResponse(res)
注:以上所有添加的方法,都要在 score/urls.py中添加上,否则页面无法访问
程序猿与投资生活实录已改名为 程序猿知秋,WX 公众号同款,欢迎关注!!