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)
name = interfaces_obj.projects.name
通过父表模型获取从表数据
class ProjectsViews(View):
def get(self, request, pk):
project_obj = Project.objects.get(id=1)
name = project_obj.interfaces_set.all()
- 可以先获取父表模型对象,然后默认可以通过
从表名称_set 获取从表数据 - 使用
project_obj.interfaces_set.all() ,可以获取所有的数据 - 同样也可以使用
filter() 进行数据过滤
上方我们想要通过父表获取到从表数据,需要 通过 父表模型对象.从表模型对象名称_set.all() 的方式获取,如果我们不想使用从表模型对象名称,想要自定义,应该怎么实现呢?
class InterFaces(BaseModel):
...
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() 这种写法则无法再获取到数据,需要换一种方式获取
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):
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
from django.db.models import Q
class ProjectsViews(View):
def get(self, request, pk):
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 = '可爱的猪猪'
project_obj.save()
指定更新某个字段
按照上方的方式,虽然数据更新了,但是他也会将我们的更新时间一起更新,如果我们不想更新这个日期,只想更新其中某一个字段,应该怎么做?
class ProjectsViews(View):
def get(self, request, pk):
project_obj = Project.objects.get(id=1)
project_obj.name = "猪猪框架"
project_obj.leader = '可爱的猪猪'
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
删除数据
删除单条数据
class ProjectsViews(View):
def get(self, request, pk):
project_obj = Project.objects.get(id=1)
project_obj.delete()
pass
删除多条数据
class ProjectsViews(View):
def get(self, request, pk):
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 语句,主要为了提升数据库性能)
|