djnago文档6
#### (5)约束选项
| 选项 | 说明 |
| :---------- | ------------------------------------------------------------ |
| null | 如果为True,表示允许为空,默认值是False。相当于python的None |
| blank | 如果为True,则该字段允许为空白,默认值是False。 相当于python的空字符串,“” |
| db_column | 字段的名称,如果未指定,则使用属性的名称。 |
| db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False。 相当于SQL语句中的key |
| default | 默认值,当不填写数据时,使用该选项的值作为数据的默认值。 |
| primary_key | 如果为True,则该字段会成为模型的主键,默认值是False,一般不用设置,系统默认设置。 |
| unique | 如果为True,则该字段在表中必须有唯一值,默认值是False。相当于SQL语句中的unique |
**注意:null是数据库范畴的概念,blank是表单验证范畴的**
#### (6) 外键
在设置外键时,需要通过**on_delete**选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
- **CASCADE** 级联,删除主表数据时连通一起删除外键表中数据
- **PROTECT** 保护,通过抛出**ProtectedError**异常,来阻止删除主表中被外键应用的数据
- **SET_NULL** 设置为NULL,仅在该字段null=True允许为null时可用
- **SET_DEFAULT** 设置为默认值,仅在该字段设置了默认值时可用
- **SET()** 设置为特定值或者调用特定方法,例如:
```python
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class UserModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)
```
- **DO_NOTHING** 不做任何操作,如果数据库前置指明级联性,此选项会抛出**IntegrityError**异常
商品分类表
| id | category | |
| ---- | -------- | ---- |
| 1 | 蔬菜 | |
| 2 | 电脑 | |
商品信息表
| id | goods_name | cid |
| ---- | ------------ | ---- |
| 1 | 冬瓜 | 1 |
| 2 | 华为笔记本A1 | 2 |
| 3 | 茄子 | 1 |
> 1. 当模型字段的on_delete=CASCADE, 删除蔬菜(id=1),则在外键cid=1的商品id1和3就被删除。
>
> 2. 当模型字段的on_delete=PROTECT,删除蔬菜,mysql自动检查商品信息表,有没有cid=1的记录,有则提示必须先移除掉商品信息表中,id=1的所有记录以后才能删除蔬菜。
>
> 3. 当模型字段的on_delete=SET_NULL,删除蔬菜以后,对应商品信息表,cid=1的数据的cid全部被改成cid=null
>
> 4. 当模型字段的on_delete=SET_DEFAULT,删除蔬菜以后,对应商品信息表,cid=1的数据记录的cid被被设置默认值。
## 6.3、数据迁移
将模型类定义表架构的代码转换成SQL同步到数据库中,这个过程就是数据迁移。django中的数据迁移,就是一个类,这个类提供了一系列的终端命令,帮我们完成数据迁移的工作。
#### (1)生成迁移文件
所谓的迁移文件, 是类似模型类的迁移类,主要是描述了数据表结构的类文件.
```python
python manage.py makemigrations
```
#### (2)同步到数据库中
```python
python manage.py migrate
```
补充:在django内部提供了一系列的功能,这些功能也会使用到数据库,所以在项目搭建以后第一次数据迁移的时候,会看到django项目中其他的数据表被创建了。其中就有一个django内置的admin站点管理。
```
# admin站点默认是开启状态的,我们可以通过http://127.0.0.1:8000/admin
# 这个站点必须有个管理员账号登录,所以我们可以在第一次数据迁移,有了数据表以后,就可以通过以下终端命令来创建一个超级管理员账号。
python manage.py createsuperuser
```


#### (3)添加测试数据
```sql
INSERT INTO `db_student`
(`id`,`name`,`sex`,`class`,`age`,`description`,`created_time`,`updated_time`)
VALUES
(1,'赵华',1,307,22,'对于勤奋的人来说,成功不是偶然;对于懒惰的人来说,失败却是必然。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(2,'程星云',1,301,20,'人生应该如蜡烛一样,从顶燃到底,一直都是光明的。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(3,'陈峰',1,504,21,'在不疯狂,我们就老了,没有记忆怎么祭奠呢?','2020-11-20 10:00:00','2020-11-20 10:00:00'),(4,'苏礼就',1,502,20,'不要为旧的悲伤,浪费新的眼泪。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(5,'张小玉',2,306,18,'没有血和汗水就没有成功的泪水。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(6,'吴杰',1,307,19,'以大多数人的努力程度之低,根本轮不到去拼天赋','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(7,'张小辰',2,405,19,'人生的道路有成千上万条, 每一条路上都有它独自的风景。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(8,'王丹丹',2,502,22,'平凡的人听从命运,坚强的人主宰命运。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(9,'苗俊伟',1,503,22,'外事找谷歌,内事找百度。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(10,'娄镇明',1,301,22,'不经三思不求教,不动笔墨不读书。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(11,'周梦琪',2,306,19,'学习与坐禅相似,须有一颗恒心。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(12,'欧阳博',1,503,23,'春去秋来,又一年。What did you get ?','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(13,'颜敏莉',2,306,20,'Knowledge makes humble, ignorance makes proud.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(14,'柳宗仁',1,301,20,'有志者事竟成。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(15,'谢海龙',1,402,22,'这世界谁也不欠谁,且行且珍惜。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(16,'邓士鹏',1,508,22,'青,取之于蓝而青于蓝;冰,水为之而寒于水。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(17,'宁静',2,502,23,'一息若存 希望不灭','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(18,'上官屏儿',2,502,21,'美不自美,因人而彰。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(19,'孙晓静',2,503,20,'人生本过客,何必千千结;无所谓得失,淡看风和雨。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(20,'刘承志',1,306,20,'good good study,day day up! ^-^','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(21,'王浩',1,503,21,'积土而为山,积水而为海。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(22,'钟无艳',2,303,19,'真者,精诚之至也,不精不诚,不能动人。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(23,'莫荣轩',1,409,22,'不管发生什么事,都请安静且愉快地接受人生,勇敢地、大胆地,而且永远地微笑着。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(24,'张裕民',1,303,21,'伟大的目标形成伟大的人物。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(25,'江宸轩',1,407,22,'用最少的悔恨面对过去。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(26,'谭季同',1,305,21,'人总是珍惜未得到的,而遗忘了所拥有的。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(27,'李松风',1,504,19,'明天的希望,让我们忘了今天的痛苦。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(28,'叶宗政',1,407,20,'因害怕失败而不敢放手一搏,永远不会成功。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(29,'魏雪宁',2,306,20,'成功与失败只有一纸之隔','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(30,'徐秋菱',2,404,19,'年轻是我们唯一拥有权利去编织梦想的时光。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(31,'曾嘉慧',2,301,19,'有一分热,发一分光。就令萤火一般,也可以在黑暗里发一点光,不必等候炬火。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(32,'欧阳镇安',1,408,23,'青春虚度无所成,白首衔悲补何及!','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(33,'周子涵',2,309,19,'青春是一个普通的名称,它是幸福美好的,但它也是充满着艰苦的磨炼。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(34,'宋应诺',2,501,23,'涓滴之水终可以磨损大石,不是由于它力量强大,而是由于昼夜不舍的滴坠。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(35,'白瀚文',1,305,19,'一个人假如不脚踏实地去做,那么所希望的一切就会落空。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(36,'陈匡怡',2,505,19,'一份耕耘,一份收获。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(37,'邵星芸',2,503,22,'冰冻三尺非一日之寒。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(38,'王天歌',2,302,21,'任何的限制,都是从自己的内心开始的。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(39,'王天龙',1,302,22,'再长的路,一步步也能走完,再短的路,不迈开双脚也无法到达。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(40,'方怡',2,509,23,'智者不做不可能的事情。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(41,'李伟',1,505,19,'人之所以能,是相信能。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(42,'李思玥',2,503,22,'人的一生可能燃烧也可能腐朽,我不能腐朽,我愿意燃烧起来。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(43,'赵思成',1,401,18,'合抱之木,生于毫末;九层之台,起于累土。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(44,'蒋小媛',2,308,22,'不积跬步无以至千里,不积细流无以成江河。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(45,'龙华',1,510,19,'只要持续地努力,不懈地奋斗,就没有征服不了的东西。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(46,'牧婧白夜',2,501,21,'读不在三更五鼓,功只怕一曝十寒。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(47,'江俊文',1,304,19,'立志不坚,终不济事。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(48,'李亚容',2,304,18,'Keep on going never give up.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(49,'王紫伊',2,301,22,'最可怕的敌人,就是没有坚强的信念。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(50,'毛小宁',1,501,19,'要从容地着手去做一件事,但一旦开始,就要坚持到底。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(51,'董 晴',2,507,19,'常常是最后一把钥匙打开了门。贵在坚持','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(52,'严语',2,405,18,'逆水行舟,不进则退。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(53,'陈都灵',2,503,19,'无论什么时候,不管遇到什么情况,我绝不允许自己有一点点灰心丧气。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(54,'黄威',1,301,23,'我的字典里面没有“放弃”两个字','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(55,'林佳欣',2,308,23,'梦想就是一种让你感到坚持,就是幸福的东西。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(56,'翁心颖',2,303,19,'有目标的人才能成功,因为他们知道自己的目标在哪里。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(57,'蒙毅',1,502,22,'所谓天才,就是努力的力量。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(58,'李小琳',2,509,22,'每天早上对自己微笑一下。这就是我的生活态度。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(59,'伍小龙',1,406,19,'一路上的点点滴滴才是我们的财富。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(60,'晁然',2,305,23,'人的价值是由自己决定的。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(61,'端木浩然',1,507,18,'摔倒了爬起来再哭。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(62,'姜沛佩',2,309,21,'Believe in yourself.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(63,'李栋明',1,306,19,'虽然过去不能改变,但是未来可以。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(64,'柴柳依',2,508,23,'没有实践就没有发言权。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(65,'吴杰',1,401,22,'人生有两出悲剧。一是万念俱灰;另一是踌躇满志','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(66,'杜文华',1,507,19,'有智者立长志,无志者长立志。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(67,'邓珊珊',2,510,18,'Action is the proper fruit of knowledge.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(68,'杜俊峰',1,507,23,'世上无难事,只要肯登攀。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(69,'庄信杰',1,301,22,'知识就是力量。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(70,'宇文轩',1,402,23,'如果你想要某样东西,别等着有人某天会送给你。生命太短,等不得。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(71,'黄佳怿',2,510,19,'Learn and live.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(72,'卫然',1,510,18,'神于天,圣于地。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(73,'耶律齐',1,307,23,'如果不是在海市蜃楼中求胜,那就必须脚踏实地去跋涉。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(74,'白素欣',2,305,18,'欲望以提升热忱,毅力以磨平高山。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(75,'徐鸿',1,403,23,'最美的不是生如夏花,而是在时间的长河里,波澜不惊。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(76,'上官杰',1,409,19,'生活之所以耀眼,是因为磨难与辉煌会同时出现。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(77,'吴兴国',1,406,18,'生活的道路一旦选定,就要勇敢地走到底,决不回头。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(78,'庄晓敏',2,305,18,'Never say die.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(79,'吴镇升',1,509,18,'Judge not from appearances.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(80,'朱文丰',1,304,19,'每个人都比自己想象的要强大,但同时也比自己想象的要普通。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(81,'苟兴妍',2,508,18,'Experience is the best teacher.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(82,'祝华生',1,302,21,'浅学误人。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(83,'张美琪',2,404,23,'最淡的墨水,也胜过最强的记性。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(84,'周永麟',1,308,21,'All work and no play makes Jack a dull boy.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(85,'郑心',2,404,21,'人生就像一杯茶,不会苦一辈子,但总会苦一阵子。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(86,'公孙龙馨',1,510,21,'Experience is the father of wisdom and memory the mother.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(87,'叶灵珑',2,401,19,'读一书,增一智。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(88,'上官龙',1,501,21,'别人能做到的事,自己也可以做到。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(89,'颜振超',1,303,19,'如果要飞得高,就该把地平线忘掉。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(90,'玛诗琪',2,409,22,'每天进步一点点,成功不会远。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(91,'李哲生',1,309,22,'这不是偶然的失误,是必然的结果。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(92,'罗文华',2,408,22,'好走的都是下坡路。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(93,'李康',1,509,19,'Deliberate slowly, promptly.','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(94,'钟华强',1,405,19,'混日子很简单,讨生活比较难。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(95,'张今菁',2,403,23,'不经一翻彻骨寒,怎得梅花扑鼻香。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(96,'黄伟麟',1,407,19,'与其诅咒黑暗,不如燃起蜡烛。没有人能给你光明,除了你自己。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(97,'程荣泰',1,406,22,'明天不一定更好,。但更好的明天一定会来。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(98,'范伟杰',1,508,19,'水至清则无鱼,人至察则无徒。凡事不能太执着。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(99,'王俊凯',1,407,21,'我欲将心向明月,奈何明月照沟渠。','2020-11-20 10:00:00','2020-11-20 10:00:00'),
(100,'白杨 ',1,406,19,'闪电从不打在相同的地方.人不该被相同的方式伤害两次。','2020-11-20 10:00:00','2020-11-20 10:00:00');
```
```sql
-- 作业:
-- 1. 完成学生的创建,导入上面的数据。
-- 2. 使用原来学过的SQL语句,然后对上面导入的学生信息,完成增删查改的操作。
-- 2.0 查询所有的学生信息(name,age)
SELECT name,age FROM db_student
-- 2.1 查询年龄在18-20之间的学生信息[name,age,sex]
select name,age,sex from db_student where age >=18 and age <=20;
-- 2.2 查询年龄在18-20之间的男生信息[name,age,sex]
select name,age,if(sex=1,'男','女') as sex from db_student where age >=18 and age <=20 and sex=1;
-- 2.3 查询401-406之间所有班级的学生信息[name,age,sex,class]
select name,age,sex,class from db_student where class between 401 and 406;
-- 2.4 查询401-406之间所有班级的总人数
select count(1) as c from db_student where class between 401 and 406;
-- 2.5 添加一个学生,男,刘德华,302班,17岁,"给我一杯水就行了。",'2020-11-20 10:00:00','2020-11-20 10:00:00'
insert into db_student (name,sex,class, age, description, created_time,updated_time) values ('刘德华',1,'302', 17, "给我一杯水就行了。",'2020-11-20 10:00:00','2020-11-20 10:00:00');
-- 2.6 修改刘德华的年龄,为19岁。
update db_student set age=19 where name='刘德华';
-- 2.7 刘德华毕业了,把他从学生表中删除
delete from db_student where name='刘德华';
-- 2.8 找到所有学生中,年龄最小的5位同学和年龄最大的5位同学
select * from db_student order by age asc limit 5;
select * from db_student order by age desc limit 5;
-- 2.9 【进阶】找到所有班级中人数超过4个人班级出来
select class,count(id) as total from db_student group by class having total >= 4;
-- 2.10【进阶】把上面2.8的要求重新做一遍,改成一条数据实现
(select * from db_student order by age asc limit 5) union all (select * from db_student order by age desc limit 5);
```
## 6.4、数据库基本操作
### 6.4.1、添加记录
#### (1)save方法
通过创建模型类对象,执行对象的save()方法保存到数据库中。
```python
student = Student(
name="刘德华",
age=17,
sex=True,
clasmate=301,
description="一手忘情水"
)
student.save()
print(student.id) # 判断是否新增有ID
```
#### (2)create方法
通过模型类.objects.create()保存,返回生成的模型类对象。
```python
student = Student.objects.create(
name="赵本山",
age=50,
sex=True,
class_number=301,
description="一段小品"
)
print(student.id)
```
### 6.4.2、基础查询
ORM中针对查询结果的限制,提供了一个查询集[QuerySet].这个QuerySet,是ORM中针对查询结果进行保存数据的一个类型,我们可以通过了解这个QuerySet进行使用,达到查询优化,或者限制查询结果数量的作用。
#### (1)all()
查询所有对象,返回queryset对象。查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
```python
students = Student.objects.all()
print("students:",students)
```
#### (2)filter()
筛选条件相匹配的对象,返回queryset对象。
```python
# 查询所有的女生
students = Student.objects.filter(sex=0)
print(students)
```
#### (3)get()
返回与所给筛选条件相匹配的对象,返回结果有且只有一个, 如果符合筛选条件的对象超过一个或者没有都会抛出错误。
```python
student = Student.objects.get(pk=1)
print(student)
print(student.description)
get使用过程中的注意点:get是根据条件返回多个结果或者没有结果,都会报错
try:
student = Student.objects.get(name="刘德华")
print(student)
print(student.description)
except Student.MultipleObjectsReturned:
print("查询得到多个结果!")
except Student.DoesNotExist:
print("查询结果不存在!")
```
#### (4)first()、last()
分别为查询集的第一条记录和最后一条记录
```python
# 没有结果返回none,如果有多个结果,则返回模型对象
students = Student.objects.all()
# print(students.name)
print(students[0].name)
stu01 = Student.objects.first()
stu02 = Student.objects.last()
print(stu01.name)
print(stu02.name)
```
#### (5)exclude()
筛选条件不匹配的对象,返回queryset对象。
```python
# 查询张三以外的所有的学生
students = Student.objects.exclude(name="张三")
print(students)
```
#### (6)order_by()
对查询结果排序
```python
# order_by("字段") # 按指定字段正序显示,相当于 asc 从小到大
# order_by("-字段") # 按字段倒序排列,相当于 desc 从大到小
# order_by("第一排序","第二排序",...)
# 查询所有的男学生按年龄从高到低展示
# students = Student.objects.all().order_by("-age","-id")
students = Student.objects.filter(sex=1).order_by("-age", "-id")
print(students)
```
#### (7)count()
查询集中对象的个数
```python
# 查询所有男生的个数
count = Student.objects.filter(sex=1).count()
print(count)
```
#### (8)exists()
判断查询集中是否有数据,如果有则返回True,没有则返回False
````python
# 查询Student表中是否存在学生
print(Student.objects.exists())
````
#### (9)values()、values_list()
* `value()`把结果集中的模型对象转换成**字典**,并可以设置转换的字段列表,达到减少内存损耗,提高性能
* `values_list()`: 把结果集中的模型对象转换成**列表**,并可以设置转换的字段列表(元祖),达到减少内存损耗,提高性能
```python
# values 把查询结果中模型对象转换成字典
student_list = Student.objects.filter(classmate="301")
student_list = student_list.order_by("-age")
student_list = student_list.filter(sex=1)
ret1 = student_list.values() # 默认把所有字段全部转换并返回
ret2 = student_list.values("id","name","age") # 可以通过参数设置要转换的字段并返回
ret3 = student_list.values_list() # 默认把所有字段全部转换并返回
ret4 = student_list.values_list("id","name","age") # 可以通过参数设置要转换的字段并返回
print(ret4)
return JsonResponse({},safe=False)
```
#### (10)distinct()
从返回结果中剔除重复纪录。返回queryset。
````python
# 查询所有学生出现过的年龄
print(Student.objects.values("age").distinct())
````
### 6.4.3、模糊查询
#### (1)模糊查询之contains
> 说明:如果要包含%无需转义,直接写即可。
例:查询姓名包含'华'的学生。
```python
Student.objects.filter(name__contains='华')
```
#### (2)模糊查询之startswith、endswith
例:查询姓名以'文'结尾的学生
```python
Student.objects.filter(name__endswith='文')
```
> 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
#### (3)模糊查询之isnull
例:查询个性签名不为空的学生。
```python
# 修改Student模型description属性允许设置为null,然后数据迁移
description = models.TextField(default=None, null=True, verbose_name="个性签名")
# 添加测试数据
NSERT INTO student.db_student (name, age, sex, class, description, created_time, updated_time) VALUES ('刘德华', 17, 1, '407', null, '2020-11-20 10:00:00.000000', '2020-11-20 10:00:00.000000');
# 代码操作
tudent_list = Student.objects.filter(description__isnull=True)
```
#### (4)模糊查询之in
例:查询编号为1或3或5的学生
```python
Student.objects.filter(id__in=[1, 3, 5])
```
#### (5)模糊查询之比较查询
- **gt** 大于 (greater then)
- **gte** 大于等于 (greater then equal)
- **lt** 小于 (less then)
- **lte** 小于等于 (less then equal)
例:查询编号大于3的学生
```python
Student.objects.filter(id__gt=3)
```
#### (6)模糊查询之日期查询
**year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。**
例:查询2010年被添加到数据中的学生。
```python
Student.objects.filter(born_date__year=1980)
```
例:查询2016年6月20日后添加的学生信息。
```python
from django.utils import timezone as datetime
student_list = Student.objects.filter(created_time__gte=datetime.datetime(2016,6,20),created_time__lt=datetime.datetime(2016,6,21)).all()
print(student_list)
```
### 6.4.4、进阶查询
#### (1) F查询
之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢? 答:使用F对象,被定义在django.db.models中。
语法如下:
```sql
"""F对象:2个字段的值比较"""
# 获取从添加数据以后被改动过数据的学生
from django.db.models import F
# SQL: select * from db_student where created_time=updated_time;
student_list = Student.objects.exclude(created_time=F("updated_time"))
print(student_list)
```
#### (2) Q查询
**多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。**
例:查询年龄大于20,并且编号小于30的学生。
```python
Student.objects.filter(age__gt=20,id__lt=30)
或
Student.filter(age__gt=20).filter(id__lt=30)
```
**如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符**,Q对象被义在django.db.models中。
语法如下:
```text
Q(属性名__运算符=值)
Q(属性名__运算符=值) | Q(属性名__运算符=值)
```
例:查询年龄小于19或者大于20的学生,使用Q对象如下。
```python
from django.db.models import Q
student_list = Student.objects.filter( Q(age__lt=19) | Q(age__gt=20) ).all()
```
**Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或****
例:查询年龄大于20,或编号小于30的学生,只能使用Q对象实现
```python
Student.objects.filter(Q(age__gt=20) | Q(pk__lt=30))
```
`Q对象左边可以使用~操作符,表示非not。但是工作中,我们只会使用Q对象进行或者的操作,只有多种嵌套复杂的查询条件才会使用&和~进行与和非得操作`。
例:查询编号不等于30的学生。
```python
Student.objects.filter(~Q(pk=30))
```
#### (3)聚合查询
使用aggregate()过滤器调用聚合函数。聚合函数包括:**Avg** 平均,**Count** 数量,**Max** 最大,**Min** 最小,**Sum** 求和,被定义在django.db.models中。
例:查询学生的平均年龄。
```python
from django.db.models import Sum,Count,Avg,Max,Min
Student.objects.aggregate(Avg('age'))
```
注意:aggregate的返回值是一个字典类型,格式如下:
```python
{'属性名__聚合类小写':值}
```
使用count时一般不使用aggregate()过滤器。
例:查询学生总数。
```python
Student.objects.count() # count函数的返回值是一个数字。
```
#### (4)分组查询
```python
QuerySet对象.annotate()
# annotate() 进行分组统计,按前面select 的字段进行 group by
# annotate() 返回值依然是 queryset对象,增加了分组统计后的键值对
模型对象.objects.values("id").annotate(course=Count('course__sid')).values('id','course')
# 查询指定模型, 按id分组 , 将course下的sid字段计数,返回结果是 name字段 和 course计数结果
# SQL原生语句中分组之后可以使用having过滤,在django中并没有提供having对应的方法,但是可以使用filter对分组结果进行过滤
# 所以filter在annotate之前,表示where,在annotate之后代表having
# 同理,values在annotate之前,代表分组的字段,在annotate之后代表数据查询结果返回的字段
```
#### (5)原生查询
执行原生SQL语句,也可以直接跳过模型,才通用原生pymysql.
```python
ret = Student.objects.raw("SELECT id,name,age FROM db_student") # student 可以是任意一个模型
# 这样执行获取的结果无法通过QuerySet进行操作读取,只能循环提取
print(ret,type(ret))
for item in ret:
print(item,type(item))
```
### 6.4.5、修改记录
#### (1) 使用save更新数据
```python
student = Student.objects.filter(name='刘德华').first()
print(student)
student.age = 19
student.classmate = "303"
# save之所以能提供给我们添加数据的同时,还可以更新数据的原因?
# save会找到模型的字段的主键id的值,
# 主键id的值如果是none,则表示当前数据没有被数据库,所以save会自动变成添加操作
# 主键id有值,则表示当前数据在数据库中已经存在,所以save会自动变成更新数据操作
student.save()
```
#### (2)update更新(推荐)
**使用模型类.objects.filter().update()**,会返回受影响的行数
```python
# update是全局更新,只要符合更新的条件,则全部更新,因此强烈建议加上条件!!!
student = Student.objects.filter(name="赵华",age=22).update(name="刘芙蓉",sex=True)
print(student)
```
### 6.4.6、删除记录
删除有两种方法
#### (1)模型类对象.delete
```python
student = Student.objects.get(id=13)
student.delete()
```
#### (2)模型类.objects.filter().delete()
```python
Student.objects.filter(id=14).delete()
```
代码:
```python
# 1. 先查询到数据模型对象。通过模型对象进行删除
# student = Student.objects.filter(pk=13).first()
# student.delete()
# 2. 直接删除
ret = Student.objects.filter(pk=100).delete()
print(ret)
# 务必写上条件,否则变成了清空表了。ret = Student.objects.filter().delete()
```