ORM 表操作和表查询
单表操作
# 增
res = models.User.objects.create(...)
user_obj = models.User(name='egon',age=84)
user_obj.save()
# 删
res = models.User.objects.filter(pk=2).delete()
user_obj = models.User.objects.filter(pk=1).first()
user_obj.delete()
# 改
models.User.objects.filter(pk=4).update(name='egonDSB')
user_obj = models.User.objects.filter(pk=6)
user_obj.name = 'egonPPP'
user_obj.save()
# 查
user_obj = models.User.objects.get(pk=4)
user_obj = models.User.objects.filter(pk=6)
get 直接返回数据对象,数据不存在,报错
filter 返回queryset,要first(),得到对象,不会报错
pk:
uid
pid
sid
...
必知必会13条
all() 查询所有数据
filter() 带有过滤条件的查询
get() 直接拿数据对象 但是条件不存在直接报错
first() 拿queryset里面第一个元素
last()
values() 可以指定获取的数据字段 列表套字典
res = models.User.objects.values('name','age')
<QuerySet [{'name': 'jason', 'age': 18}, {'name': 'egonPPP', 'age': 84}]>
values_list() 列表套元祖
res = models.User.objects.values_list('name','age')
<QuerySet [('jason', 18), ('egonPPP', 84)]>
distinct() 去重
res = models.User.objects.values('name','age').distinct()
去重一定要是一模一样的数据 如果带有主键 肯定不一样
order_by()
res = models.User.objects.order_by('age') # 默认升序
res = models.User.objects.order_by('-age') # 降序
reverse() 反转的前提是 数据已经排过序 order_by()
res = models.User.objects.all()
res1 = models.User.objects.order_by('age').reverse()
count() 统计当前数据的个数
res = models.User.objects.count()
exclude() 排除在外
res = models.User.objects.exclude(name='jason')
exists()
res = models.User.objects.filter(pk=10).exists()
查看内部sql语句的方式
# 方式1
res = models.User.objects.values_list('name','age')
# <QuerySet [('jason', 18), ('egonPPP', 84)]>
print(res.query)
queryset对象才能够点query查看内部的sql语句
# 方式2:所有的sql语句都能查看
配置文件中配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
神奇的双下划线查询
大于
res = models.User.objects.filter(age__gt=35)
小于
res = models.User.objects.filter(age__lt=35)
大于等于 小于等于
res = models.User.objects.filter(age__gte=32)
res = models.User.objects.filter(age__lte=32)
__in
res = models.User.objects.filter(age__in=[18,32,40])
__range 首尾都要
res = models.User.objects.filter(age__range=[18,40])
是否包含 模糊查询 区分大小写
res = models.User.objects.filter(name__contains='s')
忽略大小写
res = models.User.objects.filter(name__icontains='p')
res = models.User.objects.filter(name__startswith='j')
res1 = models.User.objects.filter(name__endswith='j')
查询出注册时间是 2020 1月
res = models.User.objects.filter(register_time__month='1')
res = models.User.objects.filter(register_time__year='2020')
一对多外键增删改查
# 增
# 1 直接写实际字段 id
models.Book.objects.create(title='论语',price=899.23,publish_id=1)
# 2 虚拟字段 对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj)
# 删
models.Publish.objects.filter(pk=1).delete() # 级联删除
# 改
models.Book.objects.filter(pk=1).update(publish_id=2)
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
多对多外键增删改查
增
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(2,3)
book_obj.authors.add(author_obj1,author_obj2)
删
book_obj.authors.remove(1,3)
book_obj.authors.remove(author_obj,author_obj1)
改
book_obj.authors.set([1,2])
book_obj.authors.set([3])
book_obj.authors.set([author_obj,author_obj1])
清空
# 在第三张关系表中清空某个书籍与作者的绑定关系
book_obj.authors.clear()
正反向查询
从有外键字段的表,查相关表,为正向查询
从没有外键字段的表,查相关的有外键字段的表,为反向查询
正向查询按字段
反向查询按表名小写
_set
.all()
多表查询
子查询(基于对象的跨表查询)
结果多个.all()
结果一个,直接拿到数据对象
反向查询的时候
结果多个 必须加_set.all()
结果一个 不加_set.all()
联表查询(基于双下划线的跨表查询)
自身的字段直接写,别的关联表的字段,要 表__字段
联表查询:
在有关联的几张表中,
filter参数,本身表的条件,直接写,其它表的条件要 表__字段 参数不加引号
values参数,本身表的字段,直接写,其他表的字段要 表__字段 参数加引号
表__字段 拿到字段
表__外键__字段 拿到间接表的字段
聚合查询 aggregate
from app01 import models
from django.db.models import Max,Min,Sum,Count,Avg
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),
Count('pk'),Avg('price'))
分组查询 annotate
分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取
from django.db.models import Max, Min, Sum, Count, Avg
res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
models后面点什么 就是按什么分组
author_num是我们自己定义的字段
按照指定的字段分组
models.Book.objects.values('price').annotate()
如果出现分组查询报错的情况 需要修改数据库严格模式
F与Q查询
# F查询
直接获取表中某个字段对应的数据 可以比较两个字段的大小
from django.db.models import F
res = models.Book.objects.filter(maichu__gt=F('kucun'))
将所有书籍的价格提升500块
models.Book.objects.update(price=F('price') + 500)
将所有书的名称后面加上爆款两个字
在操作字符类型的数据的时候 F不能够直接做到字符串的拼接
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
models.Book.objects.update(title=F('title') + '爆款') # 所有的名称会全部变成空白
# Q查询
filter括号内多个参数是and关系
from django.db.models import Q
res = models.Book.objects.filter(Q(maichu__gt=100),Q(price__lt=600))
逗号 and关系
res = models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=600))
| or关系
res = models.Book.objects.filter(~Q(maichu__gt=100)|Q(price__lt=600))
~ not关系
Q的高阶用法 能够将查询条件的左边变成字符串的形式
q = Q()
q.connector = 'or'
q.children.append(('maichu__gt',100))
q.children.append(('price__lt',600))
res = models.Book.objects.filter(q) # 默认还是and关系