🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] Django的manage工具提供了shell命令,已经帮助我们配置好当前工程的运行环境(如连接好数据库等),我们会在自带终端中执行测试python语句。 `manage.py` 所在目录执行命令 ``` python manage.py shell ``` 这打开了一个交互式命令行。 导入模型类 ``` from book.models import Book from book.models import Role ``` 导入date包处理时间 ``` from datetime import date ``` ## 增 增加数据有两种方式 ### 1.save 创建模型类对象,再使用 `save` 保存到数据库中 新增书籍 “西游记” ``` book = Book( b_title="西游记", b_pub_date=date(1988,1,1), b_read=20, b_comment=10, is_delete=False) >>> book.save() ``` ### 2.create 直接保存到数据库中 “西游记”书籍新增角色 “孙悟空” ``` Role.objects.create( r_name="孙悟空", r_gender="1", r_describe="猴哥", r_book_id=book.id) ``` ## 查 ### 1.基本查询 **get** 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常,返回一个模型类对象。 **all** 查询多个结果,返回一个查询集。 **count** 查询结果数量。 #### get get 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常。 查询编号为5的书籍 ```python >>> Book.objects.get(pk=5) <Book: Book object> ``` objects 是模型管理器,会在后边有具体的讲解。 pk代表primary key的缩写,也就是任何model中都有的主键,当id也是主键的时候,我们可以认为pk和id是完全一样的。但是当model的主键不是id的时候,两者就有了区别。 输出出来的 `<Book: Book object>` 无法看出是不是我们写进去的数据,为了让显示更人性化,我们给数据库模型添加一个 `_str__` 方法。 ```python class Book(models.Model): ... def __str__(self): return self.b_title class Role(models.Model): ... def __str__(self): return self.r_name ``` 重启shell,重新导入模型类 ```python >>> Book.objects.get(id=5) <Book: 西游记> ``` #### all all 查询多个结果。 查询所有书 ```python >>> Book.objects.all() <QuerySet [<Book: 射雕英雄传>, <Book: 天龙八部>, <Book: 笑傲江湖>, <Book: 雪山飞狐>, <Book: 西游记>]> ``` #### count count 查询结果数量。 获得书籍数量 ```python >>> Book.objects.count() 5 ``` ### 2.过滤查询 过滤查询实现sql语句中的 `where` 功能,包括: **filter** 过滤出多个结果,返回一个查询集 **exclude** 排除掉符合条件剩下的结果,返回一个查询集 **get** 过滤单一结果 过滤查询语法: ``` 模型类名.objects.查询方式(过滤条件) ``` 过滤条件语法: ``` 字段名称__条件运算符=值 ``` 条件运算符: ``` exact:相等。 contains:包含。 startswith:指定值开头 endswith:指定值结尾 isnull:是否为null。 in:是否包含在范围内。 gt: 大于 (greater then) gte: 大于等于 (greater then equal) lt: 小于 (less then) lte: 小于等于 (less then equal) year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。 ``` #### 相等 exact:表示相等 查询书名等于“西游记”的书 ```python >>> Book.objects.filter(b_title__exact="西游记") <QuerySet [<Book: 西游记>]> ``` #### 包含(模糊查询) contains:包含 书名包含“八”字的书 ```python >>> Book.objects.filter(b_title__contains="八") <QuerySet [<Book: 天龙八部>]> ``` #### 开头 书名“笑”开头的数 ```python >>> Book.objects.filter(b_title__startswith="笑") <QuerySet [<Book: 笑傲江湖>]> ``` #### 结尾 ```python >>> Book.objects.filter(b_title__endswith="狐") <QuerySet [<Book: 雪山飞狐>]> ``` #### 空 isnull:是否为null 书名不为空 ```python >>> Book.objects.filter(b_title__isnull=False) <QuerySet [<Book: 射雕英雄传>, <Book: 天龙八部>, <Book: 笑傲江湖>, <Book: 雪山飞狐>, <Book: 西游记>]> ``` #### 包含(范围) in:是否包含在范围内 编号 1,2,3的书 ```python >>> Book.objects.filter(pk__in=[1, 2, 3]) <QuerySet [<Book: 射雕英雄传>, <Book: 天龙八部>, <Book: 笑傲江湖>]> ``` #### 大于小于 ``` gt: 大于 (greater then) gte: 大于等于 (greater then equal) lt: 小于 (less then) lte: 小于等于 (less then equal) ``` 编号大于3的书 ```python >>> Book.objects.filter(pk__gt=3) <QuerySet [<Book: 雪山飞狐>, <Book: 西游记>]> ``` #### 时间 year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。 1995年的书 ```python >>> Book.objects.filter(b_pub_date__year="1995") <QuerySet [<Book: 笑傲江湖>]> ``` ### 3. F对象 F()是代表模型字段的值,可以用来修改字段或者比较字段。 导入F对象 ```python from django.db.models import F ``` F对象使用 ```python F(字段名) ``` 阅读量大于评论量 ```python >>> Book.objects.filter(b_read__gt=F('b_comment')) <QuerySet [<Book: 雪山飞狐>, <Book: 西游记>]> ``` 阅读量大于评论量两倍 ```python >>> Book.objects.filter(b_read__gt=F('b_comment')*2) <QuerySet [<Book: 雪山飞狐>]> ``` ### 4. Q对象 随着程序的复杂,查询条件也会越来越复杂,类似前边的查询语句也会变得越来越长。 例如查询阅读量大于20且评论数大于30的书,需要这样 ```python >>> book = Book.objects.filter(b_read__gt=20) >>> book.filter(b_comment__gt=30) <QuerySet [<Book: 天龙八部>]> ``` 或者这样 ```python >>> Book.objects.filter(b_read__gt=20).filter(b_comment__gt=30) <QuerySet [<Book: 天龙八部>]> ``` 但是这样的语句是相当繁杂且不利于阅读的。 **Q()对象就是为了将这些条件组合起来。** Q对象可以使用 `&` `|` `~` 连接,`&` 表示逻辑与, `|` 表示逻辑或,`~` 表示非。 类似sql语句中where部分的 `and` `or` `not` 关键字。 导入Q对象 ```python from django.db.models import Q ``` 使用Q对象实现查询阅读量大于20且评论数大于30的书 ```python >>> Book.objects.filter(Q(b_read__gt=20)&Q(b_comment__gt=30)) <QuerySet [<Book: 天龙八部>]> ``` ### 5. 聚合函数 使用aggregate()过滤器调用聚合函数。聚合函数包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 求和。 需要从 `django.db.models` 中导入,例如 ```python from django.db.models import Sum ``` 查询最多阅读数 ```python >>> Book.objects.aggregate(Max('b_read')) {'b_read__max': 58} ``` 聚合函数查询结果是一个字典类型 ``` {'字段名__聚合类小写': 查询结果} ``` ### 6. 排序 使用 `order_by` 对查询结果排序,返回一个查询集。 按阅读量排序 ```python >>> Book.objects.all().order_by('b_read') # 升序排序 <QuerySet [<Book: 射雕英雄传>, <Book: 笑傲江湖>, <Book: 西游记>, <Book: 天龙八部>, <Book: 雪山飞狐>]> >>> Book.objects.all().order_by('-b_read') # 降序排序 <QuerySet [<Book: 雪山飞狐>, <Book: 天龙八部>, <Book: 笑傲江湖>, <Book: 西游记>, <Book: 射雕英雄传>]> ``` ### 7. 关联查询 #### 一查多 语法 ``` 一方查询对象.多方模型类名小写__set ``` 查询“天龙八部”所有的角色 ```python >>> book = Book.objects.get(b_title__exact="天龙八部") >>> book.role_set.all() <QuerySet [<Role: 乔峰>, <Role: 段誉>, <Role: 虚竹>, <Role: 王语嫣>]> ``` #### 多查一 语法 ``` 多方查询对象.多方有对应关系的字段名 ``` 查询“段誉”所在书名 ```python >>> role = Role.objects.get(r_name__exact="段誉") >>> role.r_book <Book: 天龙八部> ``` ### 8. 关联+过滤查询 #### 根据多方条件查一方 语法格式 ``` 多方模型类名小写__多方字段名__条件运算符=值 ``` 查询编号为1角色所在书籍 ```python >>> Book.objects.filter(role__id__exact=1) <QuerySet [<Book: 射雕英雄传>]> ``` 查询角色名字带“黄”字的书籍 ```python >>> Book.objects.filter(role__r_name__contains="黄") <QuerySet [<Book: 射雕英雄传>, <Book: 射雕英雄传>]> ``` 当查询条件为等于的时候可以省略条件运算符 查询编号为1角色所在书籍可以这样写 ```python >>> Book.objects.get(role__id=1) <Book: 射雕英雄传> ``` #### 根据一方条件查多方 语法格式 ``` 多方有对应关系的字段名__一方字段名__查询条件=值 ``` 查询“雪山飞狐所有角色” ```python >>> Role.objects.filter(r_book__b_title__exact="雪山飞狐") <QuerySet [<Role: 胡斐>, <Role: 苗若兰>, <Role: 程灵素>, <Role: 袁紫衣>]> ``` 查询阅读量大于30的书籍角色 ```python >>> Role.objects.filter(r_book__b_read__gt=30) <QuerySet [<Role: 乔峰>, <Role: 段誉>, <Role: 虚竹>, <Role: 王语嫣>, <Role: 胡斐>, <Role: 苗若兰>, <Role: 程灵素>, <Role: 袁紫衣>]> ``` 当查询条件是等于的时候可以省略条件运算符 查询“雪山飞狐所有角色”可以这样写 ``` >>> Role.objects.filter(r_book__b_title="雪山飞狐") <QuerySet [<Role: 胡斐>, <Role: 苗若兰>, <Role: 程灵素>, <Role: 袁紫衣>]> ``` ## 删 删除数据使用查询结果对象的 `delete` 方法 语法格式 ``` 查询结果对象.delete() ``` 删除阅读量小于20的书 ``` >>> Book.objects.filter(b_read__lt=20).delete() (6, {'book.Role': 5, 'book.Book': 1}) ``` 一般删除数据只使用逻辑删除,即修改 `is_delete` 字段为 `True` ## 改 修改数据有两种方式 ### 1. save 获得 **单个模型类** 对象,修改数据后使用save保存 ``` >>> role = Role.objects.get(id__exact=18) >>> role.r_name = "齐天大圣" >>> role.save() ``` ### 2. update 获得 **查询集** 对象,使用 `update` 方法修改数据,修改后会返回被影响数据条数 修改 `id` 大于15的角色名字为 “不知名人士” ``` >>> Role.objects.filter(id__gt=15).update(r_name="不知名人士") 4 ```