Django开发博客系统(05-QuerySet的使用)

在Model层中,Django通过objects属性来提供数据操作的接口,

比如我们想要查询所有文章的数据,只需要

Post.objects.all()

他会返回一个QuerySet对象,当我们需要用到它时,它会去db中获取数据,注意是用到的时候才会去查,而不是定义的时候去查,原因是QuerySet要支持链式操作,如果每次执行都要查询数据库的话,会影响性能,假设我要查询所有文章中状态为正常的文章,有如下代码.

posts = Post.objects.all()
available_posts = posts.filter(status=1)
print(available_posts)

如果每次都要查询数据库的话,那么我们的posts中的所有文章的数据,其实根本就没有用到,而如果是懒查询则没有这个问题,这里贴上官方文档中的解释

链式调用

链式调用就是,执行一个对象中的方法之后得到的结果还是这个对象,比如

posts = Post.objects.all().filter(status=1).filter(category_id=2)...

可以这样一直调用下去(当然也可以filter(status=1, category_id=2),但这两种写法在处理多对多时会有区别,因为我自己暂时搞得不是很懂,所以这里不多叙述以免误人,详情还请查阅官方文档)

常用的QuerySet接口

根据是否支持链式调用来分类.

支持链式调用的接口

显而易见,该类接口返回的都是QuerySet对象.

all相当于SELECT * FROM table_name,用于查询所有数据

filter根据条件过滤数据,常用的条件比如等于,不等于,大于,小于.当然也能改成

LIKE查询:

Model.objects.filter(content__contains=‘条件‘)

exclude类似filter,逻辑相反

reverse把QuerySet倒序排列

distinct去重

none返回空的QuerySet

不支持链式调用的接口

返回值不是QuerySet.

get 如果存在则返回对应的实例,不存在则会抛出DoesNotExist异常,在使用时请配合try使用.

try:
    post = Post.objects.get(id=1)
except Post.DoesNotExist:
    pass

create 用来创建一个Model对象.

post = Post.objects.create(title="5-QuerySet的使用")

get_or_create 根据条件查找,没有则创建.

update 根据条件批量更新记录.

Post.objects.filter(owner__name=‘友利奈绪‘).update(title=‘测试‘)

update_or_create 同get_or_create,用于更新.

count 用于返回QuerySet中有多少条记录

latest  返回最新的一条字段,使用时需要在Model中定义

class Meta:
    get_latest_by = <用于排序的字段>

earliest 同上,返回最早的一条记录

first 返回第一条记录

last 返回最后一条记录

exists  返回True 或 False

bulk_create  用来批量保存记录,参数是一个由对应Model对象组成的列表或者元组

in_bulk  批量查询,返回值为字典,参数为id_list和filed_name

Post.objects.in_bulk([1, 2, 3])  # 查询id为1,2,3的数据 {1: <Post>, 2: <Post>, 3: <Post>}

delete  根据条件批量删除记录

values  当我们只需要某个字段的值,不需要Model实例时,使用这个

title_list = Post.objects.filter(category_id=1).values(‘title‘)

返回的结果是包含dict的QuerySet, <QuerySet [{‘title‘: xxx}]>

values_list  类似于values, 返回的是包含tuple的QuerySet, 如果只是一个字段的话请加上flat=True

进阶接口

用于提升性能的接口,在优化项目时要考虑使用

defer  把不需要展示的字段延迟加载,比如我们要获取Post中除了content的其他字段.

posts = Post.objects.all().defer(‘content‘)
for post in posts:  # 此时会执行数据库查询,但不会加载content
    print(post.content)  # 此时会执行数据查询,获取到content

书中提到这段代码会产生N+1的查询问题,他人的说明

only  与defer接口相反, 如果只想获取content,那么使用only,其他值获取时会产生额外的查询.

select_related  用来解决外键产生的N+1问题,用代码来说明.

posts = Post.objects.all()
for post in posts:  # 产生数据库查询
    print(post.owner)  # 产生额外的数据库查询

owner是外键.

解决方法

posts = Post.objects.all().select_related(‘owner‘)
for post in posts:  # 在这里会把owner一起查出来
    print(post.owner)

prefetch_related  针对多对多的数据,用它来避免N+1.比如我们项目中的post和tag

posts = Post.objects.all().prefetch_related(‘tag‘)
for post in posts:  # 产生两条查询语句,分别查询post和tag
    print(post.tag.all())

常用的字段查询

这里只罗列了一些常用的关键字,更多的请参考文档

contains包含,用来进行相似查询

icontains同上,但忽略大小写

exact精确匹配

iexact同上,忽略大小写

in指定某个集合,比如

Post.objects.filter(id__in=[1, 2, 3])

gt大于某个值

gte大于等于

lt小于

lte小于等于

startswith  以某个字符串开头,类似 LIKE ‘<关键词>%‘

istartswith 同上,忽略大小写

endswith以某个字符串结尾

iendswith  同上,忽略大小写

range范围查询,多用于时间范围

Post.objects.filter(created_time__range=(‘2018-05-01‘, ‘2018-06-01‘))

进阶查询

F  常用于执行数据库层面的计算,避免出现多线程时的竞争状态

post = Post.objects.get(id=1)
post.pv = F(‘pv‘) + 1
post.save()

Q  用来解决OR查询,当然AND查询也可以

post = Post.objects.filter(Q(id=1) | Q(id=2))
post = Post.objects.filter(Q(id=1) & Q(title=‘‘))

Count 用来聚合查询,比如我们想要知道某个分类下有多少文章,简单的做法

category = Category.objects.get(id=1)
posts_count = category.post_set.count()

但假如我们想把这个结果放到category上,则.

categories = Category.objects.annotate(posts_count=Count(‘post‘))

这相当于给category动态增加了属性posts_count

Sum  类似于Count, 用来做合计,比如我们想要得到目前所有文章的累计访问量

Post.objects.aggregate(all_pv=Sum(‘pv‘))
#  输出结果类似: {‘all_pv‘: 488}

同时上面用到了annotate和aggregate,前者用来给QuerySet结果增加属性,后者用来直接计算结果.出了Count和Sum外,还有Avg,Min,Max等..

最后,Django还提供了SQL的接口

Post.objects.raw(‘SELECT * FROM blogApp_post‘)

可以解决QuerySet无法满足查询的情况,还能提高执行效率,不过请谨慎使用,以免提高维护成本.

详细资料请参考官方文档

原文地址:https://www.cnblogs.com/ylnx-tl/p/12604610.html

时间: 2024-09-29 18:31:16

Django开发博客系统(05-QuerySet的使用)的相关文章

Django开发博客系统(01-前言与需求分析)

原本是跟着视频学,无奈发现视频中用到的资源找不到,于是自己买了本书来进行学习,贴上JD链接.<Django企业开发实战> 我的开发环境是win10+python3.8+django3.0.4,而书上是在linux环境下进行开发的,= =(汗),先这样学下去吧,毕竟面向百度编程.写博客也是为了督促一下自己,毕竟在家里宅着容易学着学着就玩手机去了.. 书前面还有一些入门知识,这里我就直接跳到做项目的部分了. 目标是开发一个博客系统, 需求分析: 简单来说,博客分为两个部分:读者访问部分(用户端)和

Django开发博客系统(04-常用字段与属性)

Django models中常用的字段类型 数值型 这些类型都是数值相关的. l  AutoField int(11). 自增主键,Django Model默认提供,可以被重写.完整定义是 id = models.AutoField(primary_key=True) l  BooleanFueld tinyint(1). 布尔类型字段,一般用于记录状态标记. l  DecimalField decimal. 开发对数据精度要求高的业务时考虑使用,比如做支付相关,金融相关.定义时需要指定精确到多

Django开发博客系统(08-路由配置与views编写)

我们需要的页面: l  博客首页 l  博文详情页 l  分类列表页 l  标签列表页 l  友链展示页 但实际上,博客首页,分类列表页和标签列表页,本质上都是文章列表页,只有一些信息有差别.那么View大概就有三类: l  列表页: 根据不同的查询条件分别展示博客首页,分类列表页和标签列表页 l  博文详情页: 展示博文详情页 l  友链展示页: 展示所有友情链接 书上使用的环境是django1.11.1,而我使用的是3.0.4,所以路由我使用path来写,并且把路由分散开来写,让代码分工能明

Django开发博客系统(07-根据需求定制管理后台)

运行系统尝试添加用户并添加数据,出现的效果 可以看到当前登录的用户虽然是DOCTOR,但依然可以看到其他用户的文章,而且过滤器上也展示了非当前用户创建的分类,显然这是一个需要我们解决的问题. 首先解决右侧过滤器的功能,这时需要自定义过滤器,这里贴上文档中的说明 接下来我们就来编写自定义过滤器的代码: 1 class CategoryOwnerFilter(admin.SimpleListFilter): 2 """自定义过滤器只展示当前用户分类""&quo

Django开发博客系统(11-使用xadmin)

这段时间进行了前端页面的美化,实现了搜索功能与评论功能,以及配置了rss和sitemap,不过这些东西后期可能还会进行大改,所以暂时不准备讲,可能完成之后会一起说一下...吧. 另外这里贴上我的源码,不过还没有完成,有兴趣可以去看看. 今天将后台的admin替换为了xadmin,xadmin是国人创建的一个开源项目,作者github,这个项目简单来说可以完全无痛地替换admin,同时增加很多有用的功能,界面也是基于Bootstrap,相较自带的更美观. 先来看看最终完成的效果图吧 接下来就进行x

Django开发博客(基础篇)

Django开发博客(基础篇)http://www.itmin.cn/archives/918

Django开发博客- 三部曲

其实在django中实现一个功能只需要三个步骤即可,这里我姑且叫它三部曲. 这三部曲就是: 定义urls映射 定义views 定义templates 什么是URL? URL就算一个WEB地址,你在浏览器输入这个地址,然后浏览器返回相应的网页给你. 比如http://djangogirls.com是一个URL,而127.0.0.1:8000同样也是个URL,默认就是http协议的. Django中的URL工作原理 我们打开mysite/urls.py文件,会发现类似下面这样: 1234567891

Django开发博客- 部署

安装Git Git是一个被大量程序员使用的”版本控制系统”.此软件可以跟踪任何时间文件的改变,这样你以后可以随时召回某个特定版本. windows系统下面可以下载git-scm安装.除了第5步”Adjusting your PATH environment”, 需要选择”Run Git and associated Unix tools from the Windows command-line”(底部的选项).除此之外,默认值都没有问题. Linux系统的安装使用包管理器安装 123 sudo

Django开发博客 入门篇

Django是神马? Django是一个开源免费的Web框架,使用Python编写.能够让你快速写出一个Web应用, 因为它包含了绝大部分的组件,比如认证,表单,ORM,Session,安全,文件上传,页面模板等,避免了重复造轮子. 官方网站:https://www.djangoproject.com/ 笔者写这篇教程的时候,最新版本是1.9 安装Django1.9 安装python虚拟环境 为了开发应用的时候使用单独的环境,最好是安装virtual environment, 这样有很好的独立性