ORM 单表操作与多表操作
ORM
单表操作
1.创建表
2.添加记录
两种方式:1)实例化一个模型类对象 再调用save()方法
例: obj = Book() obj.save()
2) 使用模型表下的objects管理器,用于对表记录增删改查等操作
例: obj = Book.objects.create()
3.查询记录
1)查询API
Part1. 除了count 其他返回的都是一个记录对象
get(**kwargs) 注意:如果没有筛选出来就会抛出错误
first()
last()
count() 注意:返回的是表中所包含的记录对象数量
Part2. 下述方法返回值均是QuerySet类型的对象 这是ORM自定义的一种数据类型
filter(**kwargs) 筛选包含的
exclude(**kwargs) 筛选不包含的
all()
order_by(*field) 注意:参数为指定的字段 默认是升序 降序是("-id")
values(*field) 注意:输出的是列表套字典 <QuerySet [{'id':1,'name':'zzp'},{}]>
values_list(*field) 注意:输出的是列表套元组 <QuerySet [(1,'zzp'),(),()]>
Part3.
1.QuerySet对象支持索引操作 QuerySet也就相当于一个大列表
2.QuerySet 支持链式操作 可以使用多个 Part2中的方法
Part4. 其他查询API
reverse() 返回值为QuerySet对象 对排序结果取反
exists() 返回值是布尔值 判断是否存在
distinct() 从values 或 values_list的返回结果中剔除 重复的记录对象 返回值是QuerySet对象
2)基于双下划线的模糊查询
filter(id__in=[1,2,3]) select*from book where id in (1,2,3);
filter(id__gt=3) >3
filter(id__lt=3) <3
filter(id__gte=3) >=3
filter(id__lte=3) <=3
filter(id__range=[1,3]) select *from book where id between 1 and 3
filter(name__contains="IN") like模糊查询 区分大小写
filter(name__icontains="in") like模糊查询 不区分大小写
filter(name__startwith="西")
filter(name__isstartwith="记")
filter(birth__year=1996) select*from user where birth between '1996-1-1' and '1996-12-31';
filter(birth__month=1)
3)F与Q查询
F查询 查询引用字段的值
案例: from django.db.modles import F
Book.objects.all().update(price=F("price")+30)
Q查询
前提:filter(id=1,name='zzp') 这里的筛选中逗号,相当于 and 条件 两者都满足的情况下
而当我们需要 or 条件是 就可以使用 Q查询
重点: 1.Q对象可以使用 ~ 操作符取反 相当于NOT
2.如果有多个过滤条件而且既有or 又有 and时,需要Q对象与关键字参数混用 此时Q对象必须在关 键字参数前面
案例:
from django.db.models import Q
User.objects.filter(~Q(id__gt=5) | Q(name='zzp'),salary__lt=100)
4)聚合查询 aggregate
案例: from django.db.models import Avg,Max,Sum,Min,Max,Count
res1 = Employee.objects.all().aggregate(nums=Count('id'),Avg('salary'))
相当于SQL: select count(id) as nums,avg(salary) as salary_avg from employee;
print(res1) 输出:{'nums':10,'salary_avg':70.16}
总结: aggregate()返回值是字典类型
key默认是由“聚合字段的名称__聚合函数的名称” 就是 avg('salary')
key 也可以是自定义 就是 nums=Count('id')
5)分组查询 annotate() 相当于group by 它必须搭配values()使用
案例1:
查询每个部门下的员工数
res = Employee.objects.values('department').annotate(num=Count('id'))
相当于sql:
select department,count(id) as num from employee group by department;
print(res)
输出:<QuerySet [{'department':'财务部','num':2},{'department':'技术部','num':3}]>
案例2:
res=Employee.objects.values('department').annotate(num=Count('id')).values('num')
print(res)
输出:<QuerySet [{'num':2},{'num':3}]>
总结: 1.values()在annotate()前表示group by的字段 在后表示取值
2.filter()在annotate()前表示where条件 在后表示having
4.修改记录
1)直接修改单条记录对象
obj = Employee.objects.filter(name='zzp')[0]
obj.name = 'ZZP'
obj.save()
2)修改QuerySet中的所有记录对象
使用update()方法 该方法返回一个整数型值,表示受影响的记录条数
queryset_obj = Employee.objects.filter(id__gt=5)
rows = queryset_obj.update(name='ZZP')
5.删除记录
1)直接删除单条记录对象
obj = Employee.objects.first()
obj.delete()
2)删除QuerySet中的所有记录对象
queryset_obj = Employee.objects.filter(id__gt=5)
rows = queryset_obj.delete()
多表操作
1.创建模型 book publish author authordetail 自动生成的第三张表 book_authors
2.添加,删除,修改记录
1)添加记录
1.单表添加 不用说了
2.多表添加 插入时 会涉及到多张表 所以我们要分三种情况来说
1.一对多:book 与 publish
方式一:使用publish参数指定关联
publish_obj = Publish.objects.filter(id=1).first()
book_obj = Book.objects.create(.....,publish=pubish_obj)
方式二:使用publish_id参数指定关联
book_obj = Book.objects.create(.....,publish_id=1)
2.一对一: author与authordetail
两种方式添加与一对多相同
方式一:使用author_detail参数指定关联
方式二:使用author_detail_id参数指定关联
3.多对多:book 与 author
一共分为三步:
1.先获取书籍对象
book_obj = Book.objects.get(id=1)
2.然后获取作者对象
author_obj = Author.objects.get(id=1)
3. 最后通过书籍对象的authors关联的第三张表字段添加
book_obj.authors.add(author_obj)
2)删除,修改记录
remove()
rose = Author.objects.get(name='rose')
book_obj2 = Book.objects.get(title='西游记')
book_obj2.authors.remove(rose)
clear() 清除所有被关联对象集合
book_obj2 = Book.objects.get(title='西游记')
book_obj2.authors.clear()
set() 需要放置一个列表套对象 [obj1,obj2]
zzp = Author.objects.get(name='zzp')
rose = Author.objects.get(name='rose')
book_obj2 = Book.objects.get(title='西游记')
book_obj2.authors.set([zzp,rose])
3.查询记录
1)基于对象的跨表查询
1.一对一查询 (Author,AuthorDetail)
正向查询,按关联字段 author_detail
需求:查询作者zzp的手机号
zzp = Author.objects.filter(name='zzp').first()
print(zzp.author_detail.tel)
反向查询 按模型名(小写) author
需求:查询手机号为110的作者名
tel = AuthorDetail.objects.filter(tel='110').first()
print(tel.author.name)
2.多对一查询(Book,Publish)
正向查询,按关联字段:publish
需求:查询西游记的出版社名字
book_obj = Book.objects.filter(name='西游记').first()
print(book_obj.pubilsh.name)
反向查询,按模型名(小写)_set book_set
需求:查询国家出版社出版的所有书籍名称
publish_obj = Publish.objects.filter(name='国家出版社').first()
book_objs = publish_obj.book_set.all()
3.多对多查询 (Book,Author) 跟多对一查询一样
正向查询,按关联字段:authors
反向查询 按模型名(小写)_set book_set
2)基于双下划线的跨表查询 此查询会被orm识别为join操作
1.一对一查询(Author,AuthorDetail)
正向查询,按关联字段+双下划线 author_detail__
需求:查询作者egon的手机号
res = Author.objects.filter(name='egon').values('author_detail__tel').first()
反向查询 表名小写+双下划线 author__
需求:查询手机号为’110‘的作者名
res = AuthorDetail.objects.filter(tel='110').values('author__name').first()
2.一对多
3.多对多
总结:都是按照同样的方式查询
正向:关联字段+双下划线
反向:表名小写+双下划线
万般皆下品,唯有读书高!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!