Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作

Posted 七月的小尾巴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作相关的知识,希望对你有一定的参考价值。

django中的查询类型

我们之前文章中搜索的查询都是精准查询,如果我们需要筛选条件进行查询,如果实现?

假设我们需要筛选 id 大于1的数据


fillter

可以看到 fillter 支持多种查询条件,可以通过 Project.objects.filter(字段名称__查询类型=字段值 来进行查询。

  1. 字段名__exact=具体值,缩写形式为:字段名=具体值
  2. 字段名__gt:大于
  3. 字段名__gte:大于等于
  4. 字段名__lt:小于
  5. 字段名__lte 小于等于
  6. 字段名__contains:包含
  7. 字段名__startwith:以xxx开头
  8. 字段名__endwith:以 xxx结尾
  9. 字段名__isnull:是否为NULL
  10. 一般在查询类型前加上一个 “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()
  1. 可以先获取父表模型对象,然后默认可以通过 从表名称_set获取从表数据
  2. 使用 project_obj.interfaces_set.all() ,可以获取所有的数据
  3. 同样也可以使用 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()
  1. 如果在从表模型的外键字段指定了 related_name 参数,则需要使用 自定义的名称才能调用
  2. 如果想要通过父表参数来获取从表的数据,或者想要通过从表来获取父表的数据,我们称为 关联查询。可以使用关联查询语句: 关联字段名称_关联模型类中的字段名称_查询类型

组合查询

我们上方只是一个查询条件,如果我们此时设计到多个查询条件,应该怎么做呢?

方式一:

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)
  1. 先获取父表模型对象
  2. 将获取的父表模型对象以外键字段名称作为参数来传递

方式二:

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)
  1. 先获取父表模型对象,进行获取父表数据的id
  2. 将父表数据的主键值及以外键名_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
  1. 我们可以查询到数据之后,直接将原先的数据赋值
  2. 一定要调用 save() 方法才能保存数据
  3. 通常直接调用 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"))
  1. 可以调用 aggregate(聚合函数(‘字段名’))方法,返回字典数据
  2. 返回的字典数据中,key 为 字段名称_聚合函数名小写
  3. 可以使用关键字参数的形式,更改字段的 key 名称 aggregate(yushaoqi=Count("xxx"))

分组查询

class ProjectsViews(View):
    def get(self, request, pk):
        qs = Project.objects.values("id").annotate(Count("interfaces"))
  1. 可以使用 QuerySet对象.value(‘父表id’).annotate(聚合函数('从表模型类名小写'))
  2. 他会自动连接两张表,然后使用外键字段作为分组条件

查询集 QuerySet对象有什么特性? (面试题)

  1. 支持链式调用:可以在查询集上方多次调用 filterexclude
  2. 惰性查找 (仅仅只是在使用数据时才会执行 sql 语句,主要为了提升数据库性能)

以上是关于Django_查询类型_关联查询_聚合查询_分组查询_更新_删除操作的主要内容,如果未能解决你的问题,请参考以下文章

python 之 Django框架(orm单表查询orm多表查询聚合查询分组查询F查询 Q查询事务Django ORM执行原生SQL)

Django:表多对多查询聚合分组FQ查询事务

使用聚合函数及F/Q及分组查询

django数据查询之聚合查询和分组查询

django-分组聚合查询

Oracle_group by分组查询_深入