Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作
Posted 七月的小尾巴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作相关的知识,希望对你有一定的参考价值。
django中的查询类型
我们之前文章中搜索的查询都是精准查询,如果我们需要筛选条件进行查询,如果实现?
假设我们需要筛选 id 大于1的数据
fillter
可以看到 fillter
支持多种查询条件,可以通过 Project.objects.filter(字段名称__查询类型=字段值
来进行查询。
字段名__exact=具体值
,缩写形式为:字段名=具体值字段名__gt
:大于字段名__gte
:大于等于字段名__lt
:小于字段名__lte
小于等于字段名__contains
:包含字段名__startwith
:以xxx开头字段名__endwith
:以 xxx结尾字段名__isnull
:是否为NULL- 一般在查询类型前加上一个 “i”,可以忽略大小写,如
Project.objects.filter(字段名称__iexact=字段值
exclude
如果我们需要查询不以 2结尾的数据,可以使用 Project.objects.exclude(id__endwith=2)
,exclud 为反向查询,filter支持的查询类型都支持,我们先通过 __endwith 为 2的数据筛选出所有结尾为2的数据, 然后再通过 exclud 反向查询,查询出所有不为2的数据
class ProjectsViews(View):
def get(self, request, pk):
obj = Project.objects.filter(id__gt=1)
pass
关联查询
我们之前都是查询、创建的的单表数据,如果我们需要设计到多张表呢?应该如何操作?
获取到从表数据后,读取父表相关数据
可以通过外键字段获取父表模型对象
class ProjectsViews(View):
def get(self, request, pk):
# 先获取从表模型对象
interfaces_obj = InterFaces.objects.get(id=1)
# projects 为外键字段
name = interfaces_obj.projects.name
通过父表模型获取从表数据
class ProjectsViews(View):
def get(self, request, pk):
project_obj = Project.objects.get(id=1)
# 父表模型对象 通过 从表模型对象名称小写_set 获取数据
name = project_obj.interfaces_set.all()
- 可以先获取父表模型对象,然后默认可以通过
从表名称_set
获取从表数据 - 使用
project_obj.interfaces_set.all()
,可以获取所有的数据 - 同样也可以使用
filter()
进行数据过滤
上方我们想要通过父表获取到从表数据,需要 通过 父表模型对象.从表模型对象名称_set.all()
的方式获取,如果我们不想使用从表模型对象名称,想要自定义,应该怎么实现呢?
class InterFaces(BaseModel):
...
# 可以使用 related_name 自定义名称字段
projects = models.ForeignKey('project.Project', on_delete=models.CASCADE,
verbose_name="所属项目", help_text="所属项目", related_name="inter")
class Meta:
...
def __str__(self):
return f"Project(self.name)"
上方我们通过 related_name="inter"
定义了外键名称,此时如果我们在使用 project_obj.interfaces_set.all()
这种写法则无法再获取到数据,需要换一种方式获取
# 我们需要使用 inter 才能调用
class ProjectsViews(View):
def get(self, request, pk):
# 获取父表模型对象
project_obj = Project.objects.get(id=1)
name = project_obj.inter.all()
- 如果在从表模型的外键字段指定了
related_name
参数,则需要使用 自定义的名称才能调用 - 如果想要通过父表参数来获取从表的数据,或者想要通过从表来获取父表的数据,我们称为
关联查询
。可以使用关联查询语句:关联字段名称_关联模型类中的字段名称_查询类型
。
组合查询
我们上方只是一个查询条件,如果我们此时设计到多个查询条件,应该怎么做呢?
方式一:
class ProjectsViews(View):
def get(self, request, pk):
# 组合查询
project_obj = Project.objects.filter(name="余少琪", leader="ysq")
方式二:
class ProjectsViews(View):
def get(self, request, pk):
# 链式调用,可以多次调用 filter
project_obj = Project.objects.filter(name="余少琪").filter(leader="ysq")
或(or)查询
上方的查询,我们是需要同时满足两个查询条件,如果我们多个条件时,只需要满足其中一个,应该怎么做呢?
from django.views import View
from django.http import HttpResponse, JsonResponse
from project.models import Project
# 导入 Q 模块
from django.db.models import Q
class ProjectsViews(View):
def get(self, request, pk):
# 可以使用 Q 查询,多个 Q 对象之间如果使用 “|” ,那么为 “或” 关系
# 这里我们查询的是 项目名称包含 2 或者 leader 为 余少琪的数据
project_obj = Project.objects.filter(Q(name__contains="2") | Q(leader="余少琪"))
数据排序
# 排序只针对查询集
class ProjectsViews(View):
def get(self, request, pk):
# 通过名称升序排序
project_obj = Project.objects.filter(Q(name__contains="2") | Q(leader="余少琪")).order_by("name")
降序排序
如果我们想要通过某个字段降序排序的话,可以在该字段前面加上 -
符号,如 -name
,则表示根据名称做降序排序
project_obj = Project.objects.filter(Q(name__contains="2") | Q(leader="余少琪")).order_by("-name", "leader")
创建从表数据
方式一:
class ProjectsViews(View):
def get(self, request, pk):
project_obj = Project.objects.get(name="在线图书项目")
InterFaces.objects.create(name="xxx在线图书登陆接口", tester="珍惜", projects=project_obj)
- 先获取父表模型对象
- 将获取的父表模型对象以外键字段名称作为参数来传递
方式二:
class ProjectsViews(View):
def get(self, request, pk):
# 外键对应的复标如何传递
project_obj = Project.objects.get(name="在线图书项目")
InterFaces.objects.create(name="xxx在线图书登陆接口", tester="珍惜", projects_id=project_obj.id)
- 先获取父表模型对象,进行获取父表数据的id
- 将父表数据的主键值及以外键名_id作为参数来传递
更新操作
class ProjectsViews(View):
def get(self, request, pk):
# 外键对应的复标如何传递
# 先获取到我们需要修改的数据
project_obj = Project.objects.get(id=1)
# 获取到之后,然后我们在直接赋值
project_obj.name = "猪猪框架"
project_obj.leader = '可爱的猪猪'
# 记得一定要调用 save() 方法才会保存数据
project_obj.save()
指定更新某个字段
按照上方的方式,虽然数据更新了,但是他也会将我们的更新时间一起更新,如果我们不想更新这个日期,只想更新其中某一个字段,应该怎么做?
class ProjectsViews(View):
def get(self, request, pk):
# 外键对应的父表如何传递
project_obj = Project.objects.get(id=1)
project_obj.name = "猪猪框架"
project_obj.leader = '可爱的猪猪'
# 可以使用 save(update_fields=['xxx', 'xxx']) 方法,指定更新参数
project_obj.save(update_fields=['name', 'leader'])
pass
- 我们可以查询到数据之后,直接将原先的数据赋值
- 一定要调用
save()
方法才能保存数据 - 通常直接调用
save()
方法,会同时将数据库中的update_time
时间也会自动更新,如果我们不想更新时间,只想更新其中的某个字段,可以使用save(update_fields=['xxx', 'xxx'])
方法
同时更新多条数据
class ProjectsViews(View):
def get(self, request, pk):
# 将所有名称中包含“项目”关键字的作者名称更改为 “测试”
Project.objects.filter(name__contains="项目").update(leader="测试")
pass
删除数据
删除单条数据
# 删除单条数据,可使用 delete() 直接删除
class ProjectsViews(View):
def get(self, request, pk):
# 获取到 id 为 1 的数据
project_obj = Project.objects.get(id=1)
# delete() 方法直接删除
project_obj.delete()
pass
删除多条数据
class ProjectsViews(View):
def get(self, request, pk):
# 删除多条数据, 可以通过 filter 筛选数据,然后同样调用 delete() 进行删除
Project.objects.filter(name__contains="项目").delete()
pass
聚合查询
from django.db.models import Q, Count
class ProjectsViews(View):
def get(self, request, pk):
# 统计所有总数
qs = Project.objects.filter(name__contains="项目").aggregate(Count("id"))
# 给统计的参数设置别名
qs1 = Project.objects.filter(name__contains="项目").aggregate(yushaoqi=Count("id"))
- 可以调用
aggregate(聚合函数(‘字段名’))
方法,返回字典数据 - 返回的字典数据中,key 为
字段名称_聚合函数名小写
- 可以使用关键字参数的形式,更改字段的 key 名称
aggregate(yushaoqi=Count("xxx"))
分组查询
class ProjectsViews(View):
def get(self, request, pk):
qs = Project.objects.values("id").annotate(Count("interfaces"))
- 可以使用
QuerySet对象.value(‘父表id’).annotate(聚合函数('从表模型类名小写'))
- 他会自动连接两张表,然后使用外键字段作为分组条件
查询集 QuerySet对象有什么特性? (面试题)
- 支持链式调用:可以在查询集上方多次调用
filter
、exclude
- 惰性查找 (仅仅只是在使用数据时才会执行 sql 语句,主要为了提升数据库性能)
以上是关于Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作的主要内容,如果未能解决你的问题,请参考以下文章
python 之 Django框架(orm单表查询orm多表查询聚合查询分组查询F查询 Q查询事务Django ORM执行原生SQL)