django这些查询技巧你会了吗?

简介: django这些查询技巧你会了吗?


1.select_related

关联查询优化,只会进行「一次」查询,然后缓存结果。平时其他方法都是惰性查询,当每次取值时都会查询一次数据库。

「建议」:所有关联查询使用此方法。

假设有两张表,一张表是书籍,一张表是英雄人物:

from django.db import models
# 书籍表
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    class Meta:
        db_table = 'tb_books'
# 英雄表
class HeroInfo(models.Model):
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    hname = models.CharField(max_length=20, verbose_name='名称')
    hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
    hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')
    class Meta:
        db_table = 'tb_heros'

现在要查询所有的英雄以及他们所在的书籍名称:

heros = HeroInfo.objects.select_related('hbook').all()
# 查询之后构造一个字典
heros_dict = {}
for hero in heros:
    heros_dict[hero.hname] = hero.hbook.btitle  # 关联查询后,直接使用.取值即可,不会再进行数据库查询

1.如上 select_related 中的参数 hbook 为外键名称,它会将所关联的表中所有信息都查询出来。

2.如果书籍表 BookInfo 中还有外键,我们还想再关联查询那张表的信息,可以用如下的方式:hbook__外键名称,外键和外键之间用双下划线连接。如果有三层关系可以:外键名称__外键名称__外键名称,以此类推,快乐就完事儿了。

3.select_related 中还可以通过参数 depth 指定查询的深度。比如示例中可以改为:select_related(depth=1),它的意思就是往下查询一层。如果书籍表中还有外键,我们都想查询出来,可以:select_related(depth=2),以此类推。

4.示例中的方式是指定查询的外键,只查询了英雄类中所关联的图书。如果英雄类中有好几个外键,我们都想关联查询,参数 depth 的优势就凸显出来了,不需要详细写出每一个外键的名称。更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

最后的结果形如:

{
  '迪迦': '迪迦奥特曼',
  '武松': '水浒传',
  ...
}

2.values_list

取出指定字段,组成列表

比如我需要一个所有英雄名称的列表:['迪迦', '武松'...]。你可能想到的方法是查询出所有的英雄信息,然后遍历每个对象,将对象的名称放到指定的列表中,完成需求。使用 values_list 可以一步到位:

list(HeroInfo.objects.values_list('hname', flat=True))

2.1 详解

1.values_list 中第一个参数填写的是要查询的字段名称,此处为 hname ;第二个参数 flat 设置为 True 是为了不以元祖的形式展示,而是直接将值取出来,形如:

<QuerySet ['迪迦', '武松'...]>
# 不设置 flat 结果如下
<QuerySet [('迪迦',), ('武松',)...]>

2.有人会问:为什么外面要使用 list 方法呢?如上示例,查询结果是一个 QuerySet 对象,为了使用方便,一般根据需要转换为 python 的列表。

3.annotate

聚合函数

「需求」:统计出英雄表中男女的数量,显示聚合结果。更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

from django.db.models import Count
HeroInfo.objects.values('hgender').annotate(number=Count('hgender'))

3.1 详解

1.上方的意思是根据字段 hgender 进行分组,然后统计每组的人数,人数一列起名为 number

2.查询结果如下:

<QuerySet [{'hgender': 0, 'number': 10}, {'hgender': 1, 'number': 3}]>

3.可以看出英雄表中男性(0)为 10 人;女性(1)为 3 人。

4.「注意」valuesannotate 的顺序一定要特别关注!示例中的顺序代表根据性别分组显示聚合结果,但是反过来后就变成了先根据 hgender 统计数量,最后只取字段 hgender 的值。

也许你会想示例中既然   annotate 可以统计数量,那么直接使用去掉 values 不是好了?不对!它是统计了数量,但只是为查询的每行记录赋予了一个新字段 number ,并没有聚合结果,不如示例中那样清晰,哪个性别有几个,展示的明明白白。 更多精彩文章请关注 公众号『Pythonnote』或者『全栈技术精选』


相关文章
|
1月前
|
SQL Go 数据库
【速存】深入理解Django ORM:编写高效的数据库查询
【速存】深入理解Django ORM:编写高效的数据库查询
58 0
|
1月前
|
SQL 前端开发 Python
基于python-django的neo4j人民的名义关系图谱查询系统
基于python-django的neo4j人民的名义关系图谱查询系统
32 0
|
4月前
|
SQL 数据库 Python
Django框架数据库ORM查询操作(6)
【7月更文挑战第6天】```markdown Django ORM常用数据库操作:1) 查询所有数据2) 根据ID查询 3) 精确查询 4) 分页排序
74 1
|
5月前
|
JSON 数据库 数据格式
使用 Django Q 对象构建复杂查询条件
通过本文示例,我们展示了如何使用Django的Q对象来构建复杂的查询条件,以及如何实现分页功能。Q对象的强大之处在于它能够轻松地组合多个查询条件,支持“与”、“或”关系,极大地提高了查询的灵活性和可读性。希望本文对你在实际项目中使用Django ORM构建复杂查询有所帮助。
|
5月前
|
存储 SQL 数据处理
Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
|
5月前
|
前端开发 数据库 Python
Python Django项目下的分页和筛选查询
在Django中实现分页功能,视图函数通过`Paginator`处理数据,每页显示10条记录。URL配置支持带参数和不带参数的分页请求。前端模板使用for循环展示分页数据,包括商品信息和状态按钮,并利用分页组件导航。筛选查询视图根据GET请求的`state`参数过滤上架或下架产品,同样实现分页功能。前端添加状态选择下拉框,分页链接携带查询参数`state`确保筛选状态在翻页时保持。
|
SQL 缓存 数据库
10 Django模型 - 模型查询
10 Django模型 - 模型查询
60 0
|
6月前
|
SQL 缓存 数据库
在Python Web开发过程中:数据库与缓存,如何使用ORM(例如Django ORM)执行查询并优化查询性能?
在Python Web开发中,使用ORM如Django ORM能简化数据库操作。为了优化查询性能,可以:选择合适索引,避免N+1查询(利用`select_related`和`prefetch_related`),批量读取数据(`iterator()`),使用缓存,分页查询,适时使用原生SQL,优化数据库配置,定期优化数据库并监控性能。这些策略能提升响应速度和用户体验。
58 0
|
SQL 数据库 索引
【Django学习】(六)ORM框架_关联模型_数据创建&查询&更新&删除&过滤
【Django学习】(六)ORM框架_关联模型_数据创建&查询&更新&删除&过滤
【Django学习】(六)ORM框架_关联模型_数据创建&查询&更新&删除&过滤
|
SQL 数据库 Python