Django 模型数据查询方法

发布于 2024-03-20 08:00:12 字数 5360 浏览 18 评论 0

python3.6 Django2.2.10

django 通过 ORM 定义模型类,以下为 Person,Book 模型代码

from django.db import models
class Person(models.Model):
"""Person"""
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
age = models.IntegerField()
birthday = models.DateField(verbose_name="生日")
country = models.CharField(max_length=20)

class Book(models.Model):
"""Book 表"""
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=30)
author = models.ForeignKey(Person, verbose_name="作者", on_delete=models.DO_NOTHING, related_name="person_writed")
type = models.CharField(verbose_name="类别", max_length=30, blank=True)
price = models.IntegerField()
published_date = models.DateField(verbose_name="出版日期", auto_now=False, auto_now_add=False)

def __str__(self):
return self.name

基本查询

通过调用以下查询方法将得到一个 QuerySet 查询集,而 QuerySet 是有缓存的,尤其当查询得到的数据非常巨大时,此时可使用迭代器 queryset.iterator(),迭代器作为 python 的特性,此处不过多

get 函数

# 仅且返回一条数据,返回空和多条均报错
book = Book.objects.get(id_exact=1)
# exact 可省略
book = Book.objects.get(id=1)

all 函数

# 查询所有。返回 QuerySet 查询集(可以遍历)
books = Book.objects.all()

filter 函数

筛选出满足条件的数据,类似=。返回结果为可遍历的 QuerySet 查询集,以下列举了查询的条件

__exact 精确等于
__iexact 精确等于,忽略大小写
__contains 包含, like '%aaa%'
__icontains 包含,忽略大小写 ilike '%aaa%'
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in 存在于一个 list 范围内
__startswith 以...开头
__istartswith 以...开头 忽略大小写
__endswith 以...结尾
__iendswith 以...结尾,忽略大小写
__range 在...范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__regex 小写敏感的正则表达式
__iregex 大小写不敏感的正则表达式。
__isnull=True/False

以下为一些例子;

# 精确查询,等于,exact 可省略
books = Book.objects.filter(title__exact='神雕侠侣')
# 模糊查询,__contains 包含
books = Book.objects.filter(title__contains='侠')
# 以...开头,__startswith
books = Book.objects.filter(title__startswith='神')
# 以...结尾,__endswith
books = Book.objects.filter(title__endswith='侣')
# list 范围查询,__in
books = Book.objects.filter(title__in=['神雕侠侣','天龙八部'])
books = Book.objects.filter(id__in=[1,3,4])
# 查询 2002 年出版
books = Book.objects.filter(published_date__year=2002)
# 查询 7 月生日的
persion = Person.objects.filter(birthday__month=7)
# 查询出版时间大于等于 2010 年的书籍
books = Book.objects.filter(published_date__year__gte=2010)
# 查询出版时间小于等于 2010
books = Book.objects.filter(published_date__year__lte=2010)

exclude 函数

与 filter 方法相反,筛选出不满足条件的数据集,类似!=。同样的,返回结果是可遍历的 QureySet 查询集

exclude 方法为 filter 方法的取反

# sql 语句为:select * from person where age not between 18 and 24。
person = Person.objects.exclude(age__range=(18,24))
#

order_by 函数

对查询结果进行排序。返回可遍历的 QuerySet 查询集。

# 按照年龄大小,升序
person = Person.objects.order_by("age")
# 按照出版日期升序,排序
books = Book.objects.order_by("published_date")
# 按照出版日期降序,排序
books = Book.objects.order_by("-published_date")

聚合函数

aggregate 方法

返回使用聚合函数后的字段和值,主要用于数据的统计。

以下列举部分实例,具体代码查询条件根据业务需求实现。

from django.db.models import Avg,Count,Min,Max,Sum
# 统计所有书籍的平均售价
result = Book.objects.all().aggregate(Avg('price'))
# 统计所有作者中,小于 40 岁的人数
result = Person.objects.filter(age__lte=40).aggregate(count('id'))
# 统计金庸出版书籍的最高价格
result = Book.objects.filter(author__name='金庸').aggregate(Max('price'))
# 统计购买所有金庸出版的书籍多少钱
result = Book.objects.filter(author__name='金庸').aggregate(Sum('price'))

annotate 方法

在原来字段的基础上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)

# 分组 annotate(),查询每一个作者出版过的书的最高价
# 解析:按照作者的名字分组,就要用到 values,显示的是字段的名字,
result = Book.objects.values('authors__name').annotate(Max('price'))
# 统计每个国家的作家人数
result = Person.objects.values('country').annotate(Count('id'))

F 表达式和 Q 表达式

F 表达式

F 表达式主要用来优化 ORM 操作数据库,还是以上面 Book 表为例

# 因为成本原因,所有书的价格需要上调 5 元
# 常规代码,先从数据库中提取所有书到 python 内存中去,然后使用 Python 代码在每个价格上+10,再保存到数据库中。
# 此种方式代码冗余,耗时且占用资源。
books = Book.objects.all()
for book in books:
book.price += 5
book.save()

使用 F 表达式之后,代码如下

from django.db.models import F
Score.objects.update(grade=F('grade')+5)

Q 表达式

Q 表达式主要用来实现比较复杂的查询语句

# 以下语句查询价格大于等于 100,并且出版年限大于等于 2008 的所有书籍
books = Book.objects.filter(price__gte=100, published_date__year__gte=2008)

如果我们需要查询价格大于等于 100,或者出版年限大于等于的书籍呢。此时 Q 表达式能够满足我们的需求

# 或运算,满足两者条件之一即可
from django.db.models import Q
books = Book.objects.filter(Q(price__gte=100) | Q(published_date__year__gte=2008))

以上为或运算,Q 表达式还可以进行其它的运算,比如&(与)和~(非)等。

# 组合查询,以神开头并且价格大于 60 ,或者 id 大于 5 的书籍
books = Book.objects.filter(Q(title__startswith="神") & Q(price__gt=60) | Q(id__gt=5))
# Q 表达式与不带 Q 查询条件组合查询,不带 Q 的查询条件放在最后
books = Book.objects.filter(Q(price__gt=60) | Q(id__gt=5),title__startswith="神")
# ~ 取反,即价格不大于 60
b8 = Book.objects.filter(Q(title__startswith="神") & ~Q(price__gt=60) | Q(id__gt=5))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

时光瘦了

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文