0


【django】关联模型类中数据的增删改查操作总结

在这里插入图片描述


文章目录

一、多对一

正向操作

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

1、改

给学生对象,赋值channel字段

方法一

**

s.channel_id=关联模型对象.id

**

In [29]: s=Student.objects.get(id=3)

In [32]: ch1=Channel.objects.get(id=4)

In [33]: s.channel_id=ch1.id

In [34]: s.save()

方法二

**

s.channel=关联模型对象

**

In [35]: s=Student.objects.get(id=4)

In [36]: ch1=Channel.objects.get(id=5)

In [37]: s.channel=ch1

In [38]: s.save()

2、删

把一个学生对象的channel字段删除,如果想要删除一个外键,定义模型类时定义外键字段需要有null=True的设置
s.channel=None 直接赋值外键为None
s.save()

In [40]: s=Student.objects.get(id=4)
In [41]: s.channel=None
In [42]: s.save()

或者
s.channel_id=None 直接赋值外键为None
s.save()

In [43]: s.channel_id=None
In [44]: s.save()

查看sql

In [45]:print(connection.queries[-1]){'sql': "UPDATE `t_student` SET `name` ='james', `age` =18, `phone` ='13888888888', `address` = NULL, `create_tim
e` ='2023-01-06 07:07:17.669711', `channel_id` = NULL WHERE `t_student`.`id` =4",'time':'0.000'}

3、查

涉及跨表查询

反向操作

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

在这个模型的对象上,有一个反向字段,它的名字默认以关联模型名的小写加上_set构成,所以在Channel模型的对象上,有一个反向字段student_set,这个字段是一个关系型管理器,可以操作Student模型

In [48]: ch1.student_set
Out[48]:<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager at
0x1950e19ad90>

案例1:查询百度渠道下的所有学生信息

**

ch1.student_set.all():是查询集

**

In [46]: ch1=Channel.objects.get(id=5)

In [51]: ch1.student_set.all()
Out[51]:<QuerySet [<Student: james>,<Student: harden>]>

In [52]:print(connection.queries[-1]){'sql': 'SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`,
 `t_student`.`create_time`, `t_student`.`channel_id` FROM `t_student` WHERE `t_student`.`channel_id` =5 ORDER BY `t
_student`.`id` ASC LIMIT 21', 'time': '0.015'}

案例2:新增一个百度渠道下的学生

**

ch1.student_set.create(name='happy')

**

In [53]: ch1.student_set.create(name='happy')
Out[53]:<Student: happy>

In [54]:print(connection.queries[-1]){'sql': "INSERT INTO `t_student` (`name`, `age`, `phone`, `address`, `create_time`, `channel_id`) VALUES ('happy', N
ULL, NULL, NULL,'2023-01-07 08:19:56.927533',5) RETURNING `t_student`.`id`",'time':'0.015'}

1、增

直接创建Student对象

直接通过关系型管理器创建学生对象

channel1=Channel.objects.get(id=2)
channel1.student_set.create(name=‘happy’)

2、改

方法一:add()

把多个学生对象添加进渠道的关联对象集中

案例1:将s1,s2,s3添加到百度渠道中

**

channel1.student_set.add(模型对象1,模型对象2,......)

**

In [55]: s1,s2,s3=Student.objects.all()[:3]

In [57]: channel1=Channel.objects.get(id=5)

In [58]: channel1.student_set.add(s1,s2,s3)

In [59]:print(connection.queries[-1]){'sql':'UPDATE `t_student` SET `channel_id` = 5 WHERE `t_student`.`id` IN (2, 3, 4)','time':'0.000'}

方法二:替换对象集

**

channel1.student_set.set([模型对象1,模型对象2,......])

这个set方法会先清空clear,后添加**

案例2:将channel1模型对象下设置为学生s1和s2,之前不管channel1下面有多少学生都置为None

In [60]: channel1.student_set.set([s1,s2])

3、删

这里的删,是删关系,从channel对象的关联对象集中删除

a、从相关对象中清空指定的模型对象

案例1:清除某个渠道中的某些学生

**

ch1.student_set.remove(模型对象1,模型对象2,......)

**

In [64]: s1,s2,s3=Student.objects.all()[:3]

In [65]: channel1.student_set.remove(s1)

In [66]:print(connection.queries[-1]){'sql': 'UPDATE `t_student` SET `channel_id` = NULL WHERE (`t_student`.`channel_id` =5 AND `t_student`.`id` IN (2))', 'time': '0.000'}

b、从相关对象中清空所有的模型对象

案例2:清除某个渠道中的所有的学生

**

channel1.student_set.clear()

**

In [67]: channel1.student_set.clear()

In [68]:print(connection.queries[-1]){'sql':'UPDATE `t_student` SET `channel_id` = NULL WHERE `t_student`.`channel_id` = 5','time':'0.000'}

4、查

关联管理器的查询和普通管理器没有区别

a、查所有

ch1.student_set.all():这里的查所有,有个前提条件,就是ch1的关联学生集合

b、查询来自抖音渠道的学生名叫kobe的学生

方法一

**

ch1.student_set.filter(name='kobe')

**

方法二

**

Student.objects.filter(channel__name='抖音',name='kobe')

**

In [75]: q1=Student.objects.filter(channel__name='抖音',name='kobe')

In [76]: q2=ch1.student_set.filter(name='kobe')

In [77]:print(q1.query)
SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`, `t_stude
nt`.`create_time`, `t_student`.`channel_id` FROM `t_student` INNER JOIN `t_channel` ON (`t_student`.`channel_id` = `
t_channel`.`id`) WHERE (`t_channel`.`name` = 抖音 AND `t_student`.`name` = kobe) ORDER BY `t_student`.`id` ASC

In [78]:print(q2.query)
SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`, `t_stude
nt`.`create_time`, `t_student`.`channel_id` FROM `t_student` WHERE (`t_student`.`channel_id` =5 AND `t_student`.`na
me` = kobe) ORDER BY `t_student`.`id` ASC

c、自定义关联关系字段

在外键字段中使用related_name,可以自定义反向字段

channel = models.ForeignKey('Channel',
                                on_delete=models.RESTRICT,
                                null=True,
                                help_text='外键字段'),# 不允许删除,
                                related_name='students'

那么通过students进行操作

**

ch1.students.filter(name='kobe')

**

二、多对多

多对多两端都可以获得另一端的关系管理器,类似于多对一的反向关系

1、增

增一方面指的是创建关系对象

案例1:通过学生创建课程

**

s1.course_set.create(name='java') 

**
course_set字段和多对一的反向字段一样

案例2:通过课程创建学生

**

c1.students.create(name='hao')

**
在当前业务场景下,这个业务不对

另一方面这里的改是建立关联关系,也就是在第三张表中插入数据

案例3:有学生s1,s2,s3,课程c1,c2,c3,学生s1报名了c1,c2

**

s1.course_set.add(c1,c2)

**

In [13]: c1=Course.objects.all()[0]

In [14]: c2=Course.objects.all()[1]

In [15]: c3=Course.objects.all()[2]

In [16]: s1,s2,s3=Student.objects.all()[:3]

In [17]: s1.student_set.add(c1,c2)

In [22]:print(connection.queries[-1]){'sql':'INSERT IGNORE INTO `t_course_students` (`course_id`, `student_id`) VALUES (1, 2), (2, 2)','time':'0.015'}

案例4:学生s2,s3报名了c2

**

c2.students.add(s2,s3)

**

In [23]: c2.students.add(s2,s3)

In [24]:print(connection.queries[-1]){'sql':'INSERT IGNORE INTO `t_course_students` (`course_id`, `student_id`) VALUES (1, 3), (1, 4)','time':'0.015'}

2、删

同多对一,也有remove和clear

案例5:学生s1,去掉课程c1的报名

**

s1.course_set.remove(c1)

**

In [25]: s1.course_set.remove(c1)

In [26]:print(connection.queries[-1]){'sql': 'DELETE FROM `t_course_students` WHERE (`t_course_students`.`student_id` =2 AND `t_course_students`.`course_id` I
N (2))', 'time': '0.000'}

案例6:课程c2,去掉学生s2的报名

In [27]: c2.students.remove(s2)

In [28]:print(connection.queries[-1]){'sql': 'DELETE FROM `t_course_students` WHERE (`t_course_students`.`course_id` =1 AND `t_course_students`.`student_id` I
N (3))', 'time': '0.000'}

案例7:清空clear

**

s.course_set.clear()

**

**

c.students.clear()

**

3、改

这里的改是建立关联关系

案例8:修改学生s1的报名为c1和c2,如果学生s2还有其他的报名,会被删掉

**

s1.course_set.set([c1,c2])

**

In [29]: s1.course_set.set([c1,c2])

In [30]:print(connection.queries[-1]){'sql':'INSERT IGNORE INTO `t_course_students` (`course_id`, `student_id`) VALUES (2, 2)','time':'0.000'}

案例9:修改课程c1的报名为s1和s2,如果还有其他的学生报名, 也会被删掉

**

c1.students.set([s1,s2])

**

4、查

一般多对多,主要用来查。

案例10:查报名了某个课程的学生

**

c1.students.all()

**

案例11:查某个学生报名的课程

**

s1.course_set.all()

**

多对多字段都是关系管理器,查询方法和默认管理器一致

可定义的反向字段名

同多对一

students = models.ManyToManyField('Student',
                                      help_text='报名学生',
                                      verbose_name='报名学生'),
                                      related_name='courses'

**

s1.courses.all()

**

三、一对一

一对一和多对一很像
一对一字段,指向的是关系模型的一个对象
在被关联的模型对象上,默认有一个字段,以关联模型名的小写作为名称。
所以student对象上,有一个字段studentdetail。这个字段指向StudentDetail的对象。
如果student对象还没有关联,调用这个字段会报错

在StudentDetail对象上有一个student字段,它指向Student对象

1、增

一般一对一字段的模型,在创建的时候,必须传递一对一关系的对象

案例1:给某个学生添加学生详情

**

StudentDetail.objects.create(student=s1,city='北京',salary=20000)

**

In [36]: StudentDetail.objects.create(student=s1,city='北京',salary=20000)
Out[36]:<StudentDetail: kobe>

In [37]:print(connection.queries[-1]){'sql': "INSERT INTO `t_student_detail` (`student_id`, `city`, `company`, `station`, `salary`) VALUES (2,'北京', NULL, '
测试开发', '20000') RETURNING `t_student_detail`.`id`", 'time': '0.000'}

2、删

案例2:删除某个学生的学生详情

**

s1.studentdetail.delete()

**

3、改

案例3:修改某个学生的学生详情

**

s1.studentdetail.city='北京'
s1.save()

**

In [47]: StudentDetail.objects.create(student=s3,city='北京',salary=20000)
Out[47]:<StudentDetail: james>

In [48]: s3.studentdetail.city='长沙'

In [49]: s3.studentdetail.save()

案例4:修改某个学生详情对应学生的信息

**

sd.student.name='zs' sd.student.save()

**

4、查

不存在查

四、跨表查询

案例1:例如查询年龄大于18岁的学生都报名了那些课程?

**

Course.objects.filter(students__age__18)

**

In [51]: Course.objects.filter(students__age__gt=18)
Out[51]:<QuerySet [<Course: python开发>,<Course: 测试开发>]>

In [52]:print(connection.queries[-1]){'sql': 'SELECT `t_course`.`id`, `t_course`.`name` FROM `t_course` INNER JOIN `t_course_students` ON (`t_course`.`id` = `t
_course_students`.`course_id`) INNER JOIN `t_student` ON (`t_course_students`.`student_id` = `t_student`.`id`) WHERE `t_st
udent`.`age` >18 LIMIT 21', 'time': '0.000'}

**

Course.objects.filter(students__age__gt=18).distinct():过滤

**

In [54]: Course.objects.filter(students__age__gt=18).distinct()
Out[54]:<QuerySet [<Course: python开发>,<Course: 测试开发>]>

In [55]:print(connection.queries[-1]){'sql': 'SELECT DISTINCT `t_course`.`id`, `t_course`.`name` FROM `t_course` INNER JOIN `t_course_students` ON (`t_course`.
`id` = `t_course_students`.`course_id`) INNER JOIN `t_student` ON (`t_course_students`.`student_id` = `t_student`.`id`) WH
ERE `t_student`.`age` >18 LIMIT 21', 'time': '0.000'}

案例2:查询报名了python课程的学生?

**

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

**

In [57]: Student.objects.filter(course__name__contains='python开发')
Out[57]:<QuerySet [<Student: kobe>]>

In [58]:print(connection.queries[-1]){'sql': "SELECT `t_student`.`id`, `t_student`.`name`, `t_student`.`age`, `t_student`.`phone`, `t_student`.`address`, `t_st
udent`.`create_time`, `t_student`.`channel_id` FROM `t_student` INNER JOIN `t_course_students` ON (`t_student`.`id` = `t_c
ourse_students`.`student_id`) INNER JOIN `t_course` ON (`t_course_students`.`course_id` = `t_course`.`id`) WHERE `t_course
`.`name` LIKE BINARY '%python开发%' ORDER BY `t_student`.`id` ASC LIMIT 21",'time':'0.000'}

案例3:查询百度渠道的学生,报名了那些课程

**

Course.objects.filter(students__channel__name='百度')

**

In [3]: Course.objects.filter(students__channel__name='抖音')
Out[3]:<QuerySet [<Course: python开发>,<Course: 测试开发>,<Course: 测试开发>]>

通过关系字段加双下划线进行跨表查询。

五、执行原生SQL

1、raw()方法

返回查询集,通过在管理器上调用raw方法来实现

**

q=Student.objects.raw('select id,name' from t_student where id=2)

**

In [6]: q=Student.objects.raw('select id,name  from t_student where id=2')

In [7]: q
Out[7]:<RawQuerySet: select id,name  from t_student where id=2>

打印sql

In [8]:print(q.query)
select id,name  from t_student where id=2

取值

In [9]: q[0]
Out[9]:<Student: kobe>

In [10]: q[0].name
Out[10]:'kobe'

In [11]: q[0].age
Out[11]:20

2、执行原生查询

执行调用原生数据驱动执行sql

with connection.cursor()as cursor:
    cursor.execute("select * from t_student")
    one=cursor.fetchone()print(one)
    two=cursor.fetchmany(2)print(two)all=cursor.fetchall()print(all)

执行结果

(2,'kobe',20,None,None, datetime.datetime(2023,1,1,15,26,3,84534),5)((3,'li',20,None,None, datetime.datetime(2023,1,1,15,26,3,84534),1),(4,'james',18,'13888888888',None, datetime.datetime(2023,1,6,7,7,17,669711),5))((5,'kelai',22,'13688888888',None, datetime.datetime(2023,1,6,7,7,17,850752),1),(6,'kd',19,'13888888777',None, datetime.datetime(2023,1,6,7,7,17,875757),4),(7,'harden',18,'13888878228',None, datetime.datetime(2023,1,6,7,21,25,347180),4),(8,'curry',22,'13688883388',None, datetime.datetime(2023,1,6,7,21,25,347180),1),(9,'ad',19,'13888855577',None, datetime.datetime(2023,1,6,7,21,25,347180),1),(10,'happy',None,None,None, datetime.datetime(2023,1,7,8,19,56,927533),4))

在这里插入图片描述

标签: django python 后端

本文转载自: https://blog.csdn.net/YZL40514131/article/details/128591637
版权归原作者 敲代码敲到头发茂密 所有, 如有侵权,请联系我们删除。

“【django】关联模型类中数据的增删改查操作总结”的评论:

还没有评论