django的数据库操作-16
目录
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的书籍
>>> book.objects.get(pk=5) <book: book object>
objects 是模型管理器,会在后边有具体的讲解。
pk代表primary key的缩写,也就是任何model中都有的主键,当id也是主键的时候,我们可以认为pk和id是完全一样的。但是当model的主键不是id的时候,两者就有了区别。
输出出来的 <book: book object>
无法看出是不是我们写进去的数据,为了让显示更人性化,我们给数据库模型添加一个 _str__
方法。
class book(models.model): ... def __str__(self): return self.b_title class role(models.model): ... def __str__(self): return self.r_name
重启shell,重新导入模型类
>>> book.objects.get(id=5) <book: 西游记>
all
all 查询多个结果。
查询所有书
>>> book.objects.all() <queryset [<book: 射雕英雄传>, <book: 天龙八部>, <book: 笑傲江湖>, <book: 雪山飞狐>, <book: 西游记>]>
count
count 查询结果数量。
获得书籍数量
>>> 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:表示相等
查询书名等于“西游记”的书
>>> book.objects.filter(b_title__exact="西游记") <queryset [<book: 西游记>]>
包含(模糊查询)
contains:包含
书名包含“八”字的书
>>> book.objects.filter(b_title__contains="八") <queryset [<book: 天龙八部>]>
开头
书名“笑”开头的数
>>> book.objects.filter(b_title__startswith="笑") <queryset [<book: 笑傲江湖>]>
结尾
>>> book.objects.filter(b_title__endswith="狐") <queryset [<book: 雪山飞狐>]>
空
isnull:是否为null
书名不为空
>>> book.objects.filter(b_title__isnull=false) <queryset [<book: 射雕英雄传>, <book: 天龙八部>, <book: 笑傲江湖>, <book: 雪山飞狐>, <book: 西游记>]>
包含(范围)
in:是否包含在范围内
编号 1,2,3的书
>>> 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的书
>>> book.objects.filter(pk__gt=3) <queryset [<book: 雪山飞狐>, <book: 西游记>]>
时间
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
1995年的书
>>> book.objects.filter(b_pub_date__year="1995") <queryset [<book: 笑傲江湖>]>
3. f对象
f()是代表模型字段的值,可以用来修改字段或者比较字段。
导入f对象
from django.db.models import f
f对象使用
f(字段名)
阅读量大于评论量
>>> book.objects.filter(b_read__gt=f('b_comment')) <queryset [<book: 雪山飞狐>, <book: 西游记>]>
阅读量大于评论量两倍
>>> book.objects.filter(b_read__gt=f('b_comment')*2) <queryset [<book: 雪山飞狐>]>
4. q对象
随着程序的复杂,查询条件也会越来越复杂,类似前边的查询语句也会变得越来越长。
例如查询阅读量大于20且评论数大于30的书,需要这样
>>> book = book.objects.filter(b_read__gt=20) >>> book.filter(b_comment__gt=30) <queryset [<book: 天龙八部>]>
或者这样
>>> book.objects.filter(b_read__gt=20).filter(b_comment__gt=30) <queryset [<book: 天龙八部>]>
但是这样的语句是相当繁杂且不利于阅读的。
q()对象就是为了将这些条件组合起来。
q对象可以使用 &
|
~
连接,&
表示逻辑与, |
表示逻辑或,~
表示非。
类似sql语句中where部分的 and
or
not
关键字。
导入q对象
from django.db.models import q
使用q对象实现查询阅读量大于20且评论数大于30的书
>>> 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
中导入,例如
from django.db.models import sum
查询最多阅读数
>>> book.objects.aggregate(max('b_read')) {'b_read__max': 58}
聚合函数查询结果是一个字典类型
{'字段名__聚合类小写': 查询结果}
6. 排序
使用 order_by
对查询结果排序,返回一个查询集。
按阅读量排序
>>> 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
查询“天龙八部”所有的角色
>>> book = book.objects.get(b_title__exact="天龙八部") >>> book.role_set.all() <queryset [<role: 乔峰>, <role: 段誉>, <role: 虚竹>, <role: 王语嫣>]>
多查一
语法
多方查询对象.多方有对应关系的字段名
查询“段誉”所在书名
>>> role = role.objects.get(r_name__exact="段誉") >>> role.r_book <book: 天龙八部>
8. 关联+过滤查询
根据多方条件查一方
语法格式
多方模型类名小写__多方字段名__条件运算符=值
查询编号为1角色所在书籍
>>> book.objects.filter(role__id__exact=1) <queryset [<book: 射雕英雄传>]>
查询角色名字带“黄”字的书籍
>>> book.objects.filter(role__r_name__contains="黄") <queryset [<book: 射雕英雄传>, <book: 射雕英雄传>]>
当查询条件为等于的时候可以省略条件运算符
查询编号为1角色所在书籍可以这样写
>>> book.objects.get(role__id=1) <book: 射雕英雄传>
根据一方条件查多方
语法格式
多方有对应关系的字段名__一方字段名__查询条件=值
查询“雪山飞狐所有角色”
>>> role.objects.filter(r_book__b_title__exact="雪山飞狐") <queryset [<role: 胡斐>, <role: 苗若兰>, <role: 程灵素>, <role: 袁紫衣>]>
查询阅读量大于30的书籍角色
>>> 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