Django(8) - 表关联对象及多表查询

138 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第37天,点击查看活动详情

模型基础三表关联对象及多表查询

一,关联表数据操作

1.1,复习数据操作(增删改查)

1.g1 = Grade.objects.create(name='Django框架', num=41)
2.g2 = Grade.get_or_create(name='爬虫框架', num=39) 
3.g3 = Grade(),g3.name='Web前端',g3.num='41',g3.save()
3.g4 = Grade(name='Tornado框架', num=30),g4.save()

1.2,OneToMany(增删改查)

'''
	正向:如果一个模型有外键字段,通过这个模型对外键进行操作,比如imformation模型有一个外键字段grade,imformation对grade进行操作

	反向:一个模型如果被另外一个模型外键关联,通过这个模型对关联他的模型进行操作。比如grade被imformation模型里的grade进行外键关联,grade对student操作
'''
1),正向增删改查
1.增,改
# 通过属性赋值的方式
g1 = Grade.objects.get(pk=1)
s1 = Imformation.objects.get(pk=1)
s1.grade = g1 
s1.save()
# 通过主键的方式
g2 = Grade.objects.get(pk=2) 
s2 = Imformation.objects.get(pk=2) 
s2.grade_id = g2.id
s2.save()  
2.查
In [18]: s1.grade          # 通过s1这个学生grade这个属性
Out[18]: <Grade: Django框架班-41期>
In [19]: s1.grade_id	   # 直接操作s1的数据库字段
Out[19]: 1
In [20]: s1.grade.name	   # 通过grade联系到Grade表
Out[20]: 'Django框架'
3.删(赋值None)
In [27]: s1.grade=None                                         
In [28]: s1.save()  
​ 2),反向增删改查
'''
管理器:g1.imformation__set.all()
实际访问情况:如果一个模型有外键(eg:Imformation模型),那么这个模型的实例(eg:grade模型的实例g1)将可以通过一个管理器(返回的是Imformation模型所有实例的管理器),默认情况下,管理器的名为(imformation_set),imformation是Imformation的小写
'''
1.增
g1 = Grade.object.get(pk=2)
ns = g1.imformation_set.create(name='F', age=28) 
ns:<Imformation: (姓名:F-年龄:28-班级:2)>
# 通过Grade这个模型往Imformation这个模型里面添加
2.批量增加
s1, s2, s3 = Imformation.objects.filter(pk__lte=3)
g1.imformation_set.add(s1, s2, s3) 
3.删
g1.imformation_set.clear() 
g1.imformation_set.remove(s1)
4.改
g1.imformation_set.set([s1, s2, s3])
# 在列表里面的修改班级为当前g1,不在这个里面的即使是属于g1这个班也变成null
5.查
g1.imformation_set.all() 
g1.imformation_set.get(pk=1) 
3),修改管理器名
grade = models.ForeignKey('Grade', on_delete=models.SET_NULL, null=True, related_name='imformation')
# 把imformation_set这个管理器命名成imformation
g1 = Grade.objects.get(pk=4) 
In [2]: g1 = Grade.objects.get(pk=4)
In [3]: g1.imformation.all()  
Out[3]: <QuerySet [<Imformation: (姓名:A-年龄:19-班级:4)>, <Imformation: (姓名:B-年龄:21-班级:4)>, <Imform-年龄:25-班级:4)>]>

1.3,ManyToMany(增删改查)

'''
    正向
    eg:course里面有ManyToMany字段,模型使用该字段本身的属性名student
'''
1.增,通过中间表
s1 = Imformation.objects.get(pk=1)
c1 = Course.objects.get(name='python')
e = Enroll() 
e.studnet = s1
e.course = c1 
e.save()
2.查
c1 = Course.objects.get(pk=1) 
c1.student.all()
'''
    反向
    (原始模型的小写模型名,加上set --> course_et)
'''
1.查
s1 = Imformation.objects.get(pk=1)
s1.course_set.all() 

1.4,OneToOne

正向
1.增
In [12]: d1 = Detail(college='北京五道口某高校')
In [13]: s1
Out[13]: <Imformation: (姓名:A-年龄:19-班级:4)>
In [14]: d1.student = s1
In [15]: d1.save()  
2.查询
d1 = Detail.objects.get(pk=1)
d1.student.id
d1.student.name
反向
原始模型的小写模型名
s1.detail.college 	# 不需要写成s1.detail_set.college

二,跨表查询

Detail.objects.values('college', 'student__name', 'student__id') 
Imformation.objects.values('name', 'sex', 'detail__college') 

Imformation.objects.filter(detail__college='北京五道口某高校') # 查询学校是北京五道口...的学生
Course.objects.filter(student__sex=1)	# 男生报名的课程
Imformation.objects.filter(course_name='python')  # 报了’python‘课程的人
Imformation.objects.filter(course__name='python', grade__num=8) # 报名了python,班期为8的学生
Imformation.objects.filter(detail__college='北京五道口某高校', course__name='python')   # 查询学校是'北京...'报名课程为python的学生
Imformation.objects.filter(enroll__pay__lt=100)  # 查看缴费小于1000的学生
Grade.objects.filter(imformation__course__name='python') # 报名了python课程的班级有哪些,distinct()去重