[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
```
- 1.介绍
- 2.工程搭建
- 2.1.环境配置
- 2.2.创建工程
- 2.3.创建子应用
- 2.3.1.pycharm打开项目
- 2.4.创建视图
- 3.基本配置
- 3.1.settings基本配置项
- 3.2.路由配置
- 4.请求响应
- 4.1.request
- 4.2.response
- 4.3.cookie
- 4.4.session
- 5.类视图中间件
- 5.1.类视图
- 5.2中间件
- 6.数据库
- 6.1.数据库配置
- 6.2定义模型类
- 6.3数据库迁移
- 6.4数据库操作
- 6.5查询集
- 6.6模型管理器
- 7.模板表单
- 7.1使用模板
- 7.2模板标签
- 7.3表单
- 8.后台管理
- 8.1Admin
- 8.2自定义模型类样式
- 8.3列表页