操作背景:是在前戏2中已经创建有学生表,同时也完成了单表的查询,此篇的目的是创建关联表以及相关的关联操作
1.创建拓展表(一对一)
- 工程文件夹下app下modles.py
class StudentInfo(models.Model): s_no = models.CharField(max_length=10,null=False) phone = models.CharField(max_length=11,null=True) name = models.CharField(max_length=10,null=True) #定义一对一的关联关系 # on_delete: # models.CASCADE:删除主表,从表也会被删除 # models.PROTECT:都会被保护,但是从表可以删除 # models.SET_NULL:主表被删除,从表的外键设置为空 stu = models.OneToOneField(Student, on_delete=models.SET_NULL, related_name='info', null=True)
- 对表做修改以及添加新表后都需要迁移文件,在终端中执行代码进行迁移命令
- 方法一:
stu_info = StudentInfo() stu_info.s_no = '123456' stu_info.phone = '18328099786' stu_info.name = '小花22' #此处模型中定义为紧急联系人 stu_info.stu = Student.objects.get(id=4) # 获取学生对象进行关联 stu_info.save() return HttpResponse('创建拓展信息成功')
- 方法二:
stu_info = StudentInfo() stu_info.s_no = '123456' stu_info.phone = '18328099786' stu_info.name = '小花22' stu_info.stu_id = 5 stu_info.save() return HttpResponse('创建拓展信息成功')
(1)通过学生对象查询拓展表信息
此处用于区分关联时id的写法
- (1)创建路由
path('sel_phone_by_stu/',views.sel_phone_by_stu),
- (2)在views中写代码查询,方法一
def sel_phone_by_stu(request): # 1.查询学生对象 stu = Student.objects.filter(s_name='小花').first() stu_info = StudentInfo.objects.filter(stu_id=stu.id).first() #在获取学生对象之后关联到StudentInfo; phone = stu_info.phone print(phone) return HttpResponse('查询成功')
- (2)在views中写代码查询,方法二
def sel_phone_by_stu(request): stu = Student.objects.filter(s_name='小花').first() stu_info = StudentInfo.objects.filter(stu=stu).first() phone = stu_info.phone print(phone) return HttpResponse('查询成功')
(2)通过学生对象查询拓展表信息
此处用于区分关联时有无关联名称是的写法
- (1)创建路由,在urls.py中
path('sel_phone_by_stu2/',views.sel_phone_by_stu2),
- 没有关联名称时即》》在模型中拓展表的stu没有字段related_name=’info’,
此时的查询代码为:stu = models.OneToOneField(Student,on_delete=models.SET_NULL,null=True)
def sel_phone_by_stu2(request): # 1.查询学生对象 stu = Student.objects.filter(s_name='小花').first() # 2.反向查询,关联模型对象,关联另外一个模型名称的小写 stu_inifo = stu.studentinfo phone = stu_inifo.studentinfo print(phone) return HttpResponse('查询成功,没有关联名称')
- 有关联名称时即》》在模型中拓展表的stu字段有related_name=’info’,
def sel_phone_by_stu2(request): # 1.查询学生对象 stu = Student.objects.filter(s_name='小花').first() # 2.反向查询,直接学生对象到关联名称的名 stu_inifo = stu.info phone = stu_inifo.phone print(phone) return HttpResponse('查询成功,有关联名称的查询')
(3)通过拓展表查询学生信息
- (1)创建路由,urls中
path('sel_stu_by_info/',views.sel_stu_by_info),
- (2)先在拓展表中取出对象,关联到stu字段中,因为彼此为一对一对应的
def sel_stu_by_info(request): stu_info = StudentInfo.objects.filter(s_no='123456').first() stu = stu_info.stu print(stu.s_name) return HttpResponse('查询成功,拓展表查询学生对象。')
2 删除学生信息
- (1)创建路由
注意:在定义一对一的关联关系时,需要顶底on_delete的值path('on_delete_stu/',views.on_delete_stu),
- models.CASCADE:删除主表,从表也会被删除
- 1在models.py文件中写入代码
class Grade(models.Model): g_name = models.CharField(max_length=10,unique=True) class Meta: #此处的是定义表名 db_table = 'grade'
- (1)在前戏2中所创建的student类中
- 创建路由一对多操作,添加班级信息
path('add_grade/',views.add_grade),
- 1.添加方法一
for i in range(1,5): grade = Grade() grade.g_name = 'java180'+str(i) grade.save()
- 2.添加方法二
def add_grade(requset): for i in range(1,5): Grade.objects.create(g_name='python180'+str(i)) return HttpResponse('添加成功')
(3)给学生分配班级信息
- 1.创建路由
path('stu_grade/',views.stu_grade),
- 2.分配班级(两种方法)查询id=6的对象(对id为6的学生分配班级)
def stu_grade(requset): stu = Student.objects.get(pk=6) # # stu.g = Grade.objects.get(pk=1) stu.g_id = 4 stu.save() return HttpResponse('分配班级成功')
3.一对多的表单查询
(1)通过学生查询班级
- 创建路由
path('sel_grade_by_stu/',views.sel_grade_by_stu),
- 查询方法
def sel_grade_by_stu(request): # 1.查询姓名叫小明的对象 stu = Student.objects.filter(s_name='小明').first() grade = stu.g #此处添加了一对多的外键,因此可以得到班级的对象 print(grade.g_name) return HttpResponse('查询成功')
(2)通过班级查询学生
- 创建路由
path('sel_stu_by_grade/',views.sel_stu_by_grade),
- 查询方法一(没有创建关联名称的情况)
def sel_stu_by_grade(request): grade = Grade.objects.filter(g_name='python1801').first() stus = grade.student_set.all() # for stu in stus: print(stu.s_name,stu.s_age,stu.s_gender) return HttpResponse('查询学生成功,无关联名称')
- 查询方法一(有创建关联名称的情况);即学生表中 g = models.ForeignKey(Grade,null=True,on_delete=models.CASCADE,related_name=’stu’)中有
def sel_stu_by_grade(request): # 1.查询班级python1801 grade = Grade.objects.filter(g_name='python1801').first() stus = grade.stu.all() for stu in stus: print(stu.s_name,stu.s_age,stu.s_gender) return HttpResponse('查询学生成功,有关联名称')
4学生选课表(多对多)
(1)创建选课表
在models.py中写入代码创建选课表,同时在终端中做迁移。
- 创建路由
path('add_course/',views.add_course),
- 写入添加课程的方法一:
def add_course(request): c_names = ['大学英语','商务英语','线代','高数'] for i in c_names: course = Course() course.c_name =i course.save() return HttpResponse('添加课程成功')
- 写入添加课程的方法二:
def add_course(request): c_names = ['大学英语','商务英语','线代','高数'] for i in c_names: Course.objects.create(c_name=i) return HttpResponse
(3)给中间表添加信息(学生添加课程)
- 创建路由
两种方法的区别就在关联关系这儿path('add_s_c/',views.add_s_c),
- 添加方法一:(无关联名称)
def add_s_c(request): #1 查询课程对象 cou = Course.objects.filter(c_name='商务英语').first() #2.查询学生对象 stu = Student.objects.filter(s_name='lorry').first() # 3.加入关联关系 stu.course_set.add(cou) return HttpResponse('添加中间信息表成功')
- 添加方法二:(有关联名称cou)
def add_s_c(request): #1 查询课程对象 cou = Course.objects.filter(c_name='商务英语').first() #2.查询学生对象 stu = Student.objects.filter(s_name='lorry').first() # 3.加入关联关系 stu.cou.add(cou) return HttpResponse('添加中间信息表成功')
4.给中间表添加信息(课程添加学生)
def add_s_c(request): #将大学英语分配给小明 #1 查询课程对象 cou = Course.objects.filter(c_name='商务英语').first() #2.查询学生对象 stu = Student.objects.filter(s_name='lorry').first() cou.stu.add(stu) #前面的stu是模型中定义的stu。 return HttpResponse('添加中间信息表成功')
5.删除中间表信息
- 创建路由
path('del_s_c/',views.del_s_c)
- 写入方法
def del_s_c(requset): cou = Course.objects.filter(c_name='商务英语').first() stu = Course.objects.filter(s_name='lorry').first() stu.cou.remove(cou) return HttpResponse('删除信息成功')
5.模板(HTML的操作)
- 创建路由
后续操作:path('index/',views.index)
- a:在工程文件中创建templates的文件夹
- b:在文件夹中创建index.html文件
- c:进入文件操作解析内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>欢迎lorry</p> {% for stu in a%}
姓名:{{stu.s_name}} 年龄:{{stu.s_age}} 班级:{{ stu.g.g_name }} 选课: {% for c in stu.cou.all %} {{ c.c_name }} {% endfor %} </p> {% endfor %} </body> </html>