骄傲的赛亚人

day8关联对象操作于多表查询 有问题待解决

一对多

正向(定义外键的一方)

一个模型如果有一个外键字段,通过这个模型对外键的操作叫做正向

更新

# 创建一个渠道
ch = Channel(name='小红书')
ch.save()
# 第一种通过属性方式赋值
s1 = Student.objects.get(name='tom')
s1.channel = ch
s1.save()
# 第二种通过主键的赋值方式
s1 = Student.objects.get(name="李大毛")
ch = Channel.objects.get(name="小红书")
s1.channel_id = ch.id
s1.save()

:只有当返回 <Student: 中欧>才有save方法,返回查询集<QuerySet [<Channel: 京东>, <Channel: 小红书>]>没有save方法

 

删除

如果一个外键字段有null=True的属性,我们可以指定外键字段=None来删除关系,没指定null=True的不能删除

s1.channel = None
s1.save()

# 查询所有百度渠道的学生
# 正向查询
Student.objects.filter(channel__name="百度")  # 跨表查询   表名__属性名
# 反向查询
ch = Channel.objects.get(name="抖音")
ch.student_set.all()  # student_set是默认属性名,可以自定义更改
ch.students.all()  #  student_set更改成students后的查询

 

反向

一个模型如果被另一个模型外键关联,通过这个模型对关联它的模型进行操作叫做反向

模型A外键关联模型B,那么模型B的实例可以返回模型A的一个管理器

Student模型外键关联Channel模型,那么Channel模型的实例,默认情况下有一个属性student_set,它是一个student模型的管理器,这个属性名的规则是:模型名小写_set

注意:模型名小写_set,这个属性名可以改

通过channel模型创建student模型的数据

ch.students.create(name="殷芝", age=25, sex=1)

 增加多条数据

# 先使用切片查询出多条数据,然后使用add添加
s1,s2,s3 = Student.objects.all()[:3]
ch.students.add(s1, s2, s3)

删除

1、从相关对象中移除指定的对象

# 从抖音删除学生1,2
ch.students.remove(s1, s2)

2、从相关对象中删除所有的对象

# 删除抖音所有学生
ch.students.clear()

 改

替换对象

# 将s1,s2学生的渠道修改为抖音
ch = Channel.objects.get(name="抖音")
s1, s2 = Student.objects.all()[:2]
ch.studens.set([s1,s2])

差所有

# 小红书渠道的所有学生
ch = Channel.objects.get(name="小红书")
ch.studens.all()

 

条件查询

# 查询抖音渠道下,叫tom的学生
ch = Channel.objects.get(name="抖音")
ch.students.filter(name="tom")

 

注意:默认的管理器名字(student_set)可以更改,通过在外键字段上添加一个related_name的选项,可以修改默认管理器名字

class Student(models.Mode):
    ...
    channel = models.ForeignKey('Channel', on_delete=models.SET_NULL, null=True, verbose_name='渠道', help_text='渠道来源', related_name='students')

 

一对一

正向(定义onetoone字段的一方)

学生详情模型操作学生模型

s1 = Student.objects.get(name="李大毛")
d1 = StudentDetail(city="深圳", company="跨越")
# 属性赋值
d1.student = s1
d1.save()
# id赋值
d1.student_id = s1_id
d1.save()

反向  有问题

学生模型操作,学生详情模型

# 给学生s2添加学生详情
d2 = StudentDetail(city="深圳", company="大疆")
d2.save()
s1 = Student.objects.get(name="王玉")
s1.studentdetail = d2
s1.save()

 

和一对多的区别:

反向模型实例上的字段不再是管理器,而是一个对象。并且字段名就是模型的小写

 

多对多(定义manytomany的一方)

多对多模型两端都可以获得另一端的管理器,原理类似,一对多

添加报名记录

# 给学生添加c1,c2课程
c1, c2 = Course.objects.all()[0:2]
s1 = Student.objects.get(name="王玉")
s1.course_set.add(c1, c2)
# 给课程c1添加两名学生s1,s2
c1 = Course.objects.get(name="自动化测试")
s1, s2 = Student.objects.all()[8:10]
c1.students.add(s1, s2)

指定了第三表,还可以通过第三张表象一对多关系一样操作:

# 1. 创建一条报名记录,s1学生报名了c1这个课
s1 = Student.objects.get(name="李云龙")
c1 = Course.objects.get(name="自动化测试")
e1 = Entry()
e1.student = s1
e1.course = c1
e1.save()

 

# 想查询所有报名了c1课程的学生
c1.students.all()
# 想查询s1学生报名的所有的课程
s1.course_set.all()

跨表查询

在django的ORM中要跨表,只需要使用模型的相关字段名,并以双下划线分隔,直到你想要的字段为止

查询男生都报名了什么课程

Course.objects.filter(students__sex=1).distinct()

例如查询所有报名了python课程的学员

Student.objects.filter(course__name__contains='python')

查询,报名了python课程的百度渠道的学员

Student.objects.filter(course__name__contains='python', channel__name='百度')

查询,百度渠道的所有的订单

Entry.objects.filter(student__channel__name='百度')

执行原生SQL

1. 执行原生查询并返回模型实例

在管理器上调用raw()方法,用于执行远程SQL查询,返回模型实例:

Student.objects.raw('select * from tb_student where id=%s', params=(1,))

执行它会返回一个RawQuerySet,实例,可以迭代获取对象

for stu in Student.objects.raw('select * from tb_student where id=%s', params=(2,)):
	print(stu)

2. 直接执行自定义的SQL

from django.db import connection
def my_custom_sql():
	with connection.cursor() as cursor:
		cursor.execute('select * from tb_student where id=%s', [2])
		row = cursor.fetchone()
	return row

它返回的就是原始数据

posted on 2022-06-15 10:20  骄傲的赛亚人  阅读(25)  评论(0编辑  收藏  举报

导航