Django模型系统三
Django模型系统三
一、关系表的数据操作
1、一对多
正向:如果一个模型有外键字段,通过这个模型对外键进行操作叫做正向。
# 更新:
第一种,通过赋值的方式
In [7]: from teacher.models import Student,Grade
In [8]: g=Grade.objects.first()
In [10]: s = Student.objects.first()
In [13]: s.grade=g
In [14]: s.save()
第二种,通过主键的方式
In [15]: s2=Student.objects.last()
In [16]: s2.grade_id=g.id
In [17]: s2.save()
总结:Foreginkey 字段的更新,跟普通字段没什么区别(比如换班级,如下:)
In [18]: k = Grade.objects.create(name='python基础班',num='6')
In [19]: s2.grade=k
In [20]: s2.save()
如果要把筛选出的几条学生数据,也把班级ID赋值于它的话,要用get取出班级的对象
s = Student.objects.filter()[3:5]
g1 = Grade.objects.get(num='7')
for i in s:
i.grade=g1
i.save()
如果要更新一条数据,也要用get取出学生的对象
s=Student.objects.get(name='刘玉凤')
g = Grade.objects.get(num='8')
s.grade=g
s.save()
通过Student表中grade外键字段,去查询Grade表中信息
In [28]: res = Student.objects.filter(grade__name='django框架')
In [30]: print(res.query)
SELECT `teacher_student`.`id`, `teacher_student`.`name`, `teacher_student`.`age`, `teacher_student`.`sex`, `teacher_student`.`QQ`, `teacher_student`.`phone`, `teacher_student`.`c_time`, `teacher_student`.`e_time`, `teacher_student`.`grade_id` FROM `teacher_student` INNER JOIN `teacher_grade` ON (`teacher_student`.`grade_id` = `teacher_grade`.`id`) WHERE `teacher_grade`.`name` = django框架
# 删除:
定义:只有外键设置了null=True,你就可以通过赋值None来删除关系
In [31]: g2 = Student.objects.get(name='老徐')
In [32]: g2.grade=None
In [33]: g2.save()
# 查询:
通过Student表中grade外键字段(去过滤 ForeignKey 外键字段)去查询Student表中信息
In [34]: g3 = Student.objects.filter(grade_ _num='7')
In [35]: g3
Out[35]: <QuerySet [<Student: 沈毅>, <Student: 顾晓峰>]>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
反向:如果一个模型被另外一个模型外键关联,通过这个模型对关联它的模型进行操作叫做反向。
# 查询:
定义:通过管理器,默认管理器是有外键名称的小写加上_ _set(foo__set,foo是模型名称小写)
如果在外键字段中加了related_name='students',那么后面的查询就以students类名来查询
grade = models.ForeignKey('Grade',on_delete=models.SET_NULL, null=True,related_name='students')
g.students.filter(name='老徐') 等同于 g.Student.objects.filter(name='老徐')
# 增加:
通add方法可增加多条记录,直接操作数据库
例 :增加一条记录 g=Grade.objects.get(num='8')
s=Student.objects.get(name='老徐')
g.students.add(s)
增加多条记录 s1=Student.objects.get(pk=6) 备注:pk=6表示第6条学生表数据
s2=Student.objects.get(pk=7)
g = Grade.object.get(num='6')
g.students.add(s1,s2)
# 删除:
(删除只是删关系)通过 remove、clear 方法,直接操作数据库
g = Grade.objects.get(num='6')
res = Student.objects.get(name='老徐')
g.students.remove(res)
# 改:
通过 set方法
g = Grade.objects.get(num='8')
s1=Student.objects.get(pk=6)
s2=Student.objects.get(pk=7)
g.students.set([s1,s2])
2、多对多
定义:如果因为有额外字段,自定义了中间模型,我们需要通过中间模型的管理器,进行manytomany关系的创建和删除。
默认情况,跟一对多中的(add,create,remove,clear)用法一致。
唯一的区别是,多对多正向的时候,多对多字段就是个管理器。反向的时候,跟一对多的方向一至
c2 = Course.objects.create(name='python全栈')
s2 = Student.objects.get(age='24')
In [19]: f=Enroll()
In [20]: f.student=s2
In [21]: c2=Course.objects.get(name='python全套')
In [22]: f.course=c2
In [23]: f.paid=9288
In [24]: f.save()
3、一对一
非常类似一对一字段,增、删、改、查和普通字段没有什么区别。
反向的时候,使用模型的小写,也可以给related_name覆盖,这个就不是管理器,就是一个普通属性。
注意:一个被一对一管理的模型,它的实例,如果没有被分配关系。
In [32]: from teacher.models import StudentDetail
In [33]: dd = StudentDetail()
In [34]: s = Student.objects.get(name='沈毅')
In [35]: dd.student=s
In [36]: dd.save()
In [38]: s.studentdetail
Out[38]: <StudentDetail: StudentDetail object (1)>
In [39]: s.studentdetail.college
Out[39]: '无学校'
In [54]: s.studentdetail.college='北京大学'
In [55]: dd.save()
4、跨表查询
定义:要跨越关系,只需要使用跨越模型的相关字段的字段名,以下划线分隔,直到达到你想要的字段为止。
例:男生都报名了什么课程
In [23]: res = Course.objects.filter(students__sex=1)
In [24]: res
Out[24]: <QuerySet [<Course: python全栈>]>
去重可以这样写
In [27]: res = Course.objects.filter(students__sex=2)
In [28]: res
Out[28]: <QuerySet [<Course: python全栈>, <Course: python全栈>, <Course: python全套>]>
In [29]: res = Course.objects.filter(students__sex=2).distinct()
In [30]: res
Out[30]: <QuerySet [<Course: python全栈>, <Course: python全套>]>
例 :查询所有报了python课程的学员
In [32]: res = Student.objects.filter(course__name__contains='python')
例:查询所有报名了python全栈,在django框架班,第7期的学员
In [36]: res = Student.objects.filter(course__name='python全栈',grade__name='django框架',grade__num='7')
注:grade_ _name表示Grade表里的name字段;course__name表示Course表里的name
例:学员报名了python课程的班级有哪些
In [41]: res = Grade.objects.filter(students__course__name__contains='python').distinct()
In [42]: res
Out[42]: <QuerySet [<Grade: django框架>, <Grade: python基础班>]>
注:students是在Student里设置了 grade = models.ForeignKey('Grade',on_delete=models.SET_NULL, null=True,related_name='students')