表关系的建立
建立学院信息表、学生信息表、课程表、学生详情表,
表关系如下:
学院信息表 《= 一对多 ForeignKeyField =》 学生信息表
学生信息表 《= 一对一 OneToOneField =》 学生详细信息表
课程表 《= 多对多 ManyToManyField =》学生信息表
在model中建立以下几个模型类:
# models.py
from django.db import models
# 学院表
class Department(models.Model):
d_id = models.AutoField(primary_key=True)
d_name = models.CharField(max_length=30)
def __str__(self):
return "Department<d_id=%s,d_name=%s>"%(self.d_id,
self.d_name)
# 学生表
class Student(models.Model):
s_id = models.AutoField(primary_key=True)
s_name = models.CharField(max_length=30)
department = models.ForeignKey('Department',
null=True, #可以为空值
related_name='student', # 反向查询用(就不_set了:d1.student_set.all() -》d1.student )
on_delete=models.CASCADE) # 外键,自动关联表的主键 级联删除
def __str__(self):
return "Student<s_id=%s, s_name=%s,department_id=%s >"%(self.s_id,
self.s_name,
self.department_id)
# 学生选课表
class Course(models.Model):
c_id = models.AutoField(primary_key=True)
c_name= models.CharField(max_length=30)
student = models.ManyToManyField('Student',
related_name='course',
) # 多对多 生成第三张关系表
def __str__(self):
return "Course<c_id=%s,c_name=%s,student=%s>"%(self.c_id,
self.c_name,
self.student)
# 学生详情表
class Stu_detail(models.Model):
s_id = models.OneToOneField('Student',on_delete=models.CASCADE) # 一对一, 级联删除
s_age = models.IntegerField()
gender = models.BooleanField(default=1)
city = models.CharField(max_length=30)
def __str__(self):
return "s_id=%s,s_age=%s,s_gender=%s"%(
self.s_id,
self.s_age,
self.gender
)
执行完makemigrations 和migrate之后,会发现生成了5张表,这是因为ManyToManyField关系生成了5第三张关系表。
python manage.py shell
我们进入项目的目录,进入IDLE操作演示数据库的操作语句更方便:
1.进入IDLE
2.查看当前的目录路径
3.导入我们项目中的模型类
一对多表关系数据的添加:
往数据表student中添加数据的第一种方式:
s1 = Student(s_name='xiaoming',department_id=1)
s1.save()
往数据表student中添加数据的第二种方式:
# 先在Department里面创建一条数据d1再进行操作
s2 = Student(s_name='小红')
s2.department_id=d1
s2.save()
1.第一种方式就是跟之前的一样,用传参的方法添加,需要注意的是外键的值必须是关联表中已经存在的值.
2.第二种方式是用的属性赋值的方式,因为我们在模型类有定义了一个department的属性,而这个属性的对象的类型必须是department表的类实例对象
表关联对象的访问:
s1.department
# 属性取值,会拿到的=d1
# 通过管理器反向访问
d1.student_set.all()
# 在Foreignkey里面设置related_name='student',这样就可以直接用名字而不是_set的形式了
d1.student.all()
#这个是实例对象
s1.departmnet
# 下面3个是管理器
d1.student
s1.course
c1.student
#
处理关联对象的一些方法:
# 一对多,多的那头就有这个管理器,就有以下方法
# 管理器才能用add,create,clear,remove方法
d1 = Department.objects.get(d_id=1)
s1 = Student.objects.get(s_id=1)
c1 = Course.objects.get(c_id=1)
# print(d1,s1,c1)
print(d1.student.all()) # 查询到学院的所有学生, 通过一对多关系,管理器.all()
print(s1.department) # 模型类里面的属性,直接访问
print(c1.student) # 管理器 多对多
print(c1.student.all()) # 报名这个课程的学生
# print(s1.course_set.all()) # 学生报了哪些课, 反向查询,可以用related_name去改
print(s1.course.all()) # 学生报了哪些课, 反向查询用related_name 管理器
1.add(obj1, obj2, …) 添加的已经存在数据库的数据
添加一指定的模型对象到关联的对象集中
## add 必须是在数据库中存在的对象 :修改
d1.student.add(s1) # 将s1学生改成d1学院中
s1 = Student.objects.filter(s_id=1)
d1 = Department.objects.filter(d_id=1) filter取到的是QuerySet,类似于集合形式
d1[0].student.add(s1[1]) #先拿到某个实例对象
#例2
s6 = Student(s_name='大大', department_id=2)
s6.save() # 必须保证department字段允许为空
d1.student.add(s6) #
s6 = Student.objects.get(s_name='小小')
2.create(**kwargs) 添加不存在的数据 ,将数据直接存入数据库
创建一个新的对象,将它保存并放在关联的对象集返回新创建的对象
s1.course.create(c_name='C语言程序设计') # 会同时向两个表格添加数据
d1.student.create(s_name='小帅') # 给d1学院添加一个学生(之前不存在数据库中)
3.remove(obj1, obj2, …) 从关联的对象集中删除指定的模型对象。
删除的是关系表中的数据
s1.course.remove(c1) # 学生取消某个选修课
4.clear() 从关联的对象集中删除所有的对象
注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法
s1.course.clear() # 删除的是中间信息表的信息
多表查询—-跨关联关系的查询:
Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段:
# 查询学院名字为‘计算机学院’的学生的信息
Student.objects.filter(department__d_name='计算机学院')
它还可以反向工作。若要引用一个“反向”的关系,只需要使用该模型的小写的名称。
#查询学生名字中包含 '小' 的学生的学院信息
Department.objects.filter(student__s_name__contains='小')
# 查询学号为1的学生所有的课程
Course.objects.filter(student__s_id=1)
# 查询报了课程1的所有的学生
Student.objects.filter(course__c_id=1)
# 查询报了'python'课程的的学生的所属学院的信息
Department.objects.filter(student__course__c_name='python')