Django(17)orm查询操作
前言
查找是数据库操作中一个非常重要的技术。查询一般就是使用filter
、exclude
以及get
三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都是使用field+__+condition
的方式来使用的。以下将那些常用的查询条件来一一解释。
查询条件
exact
使用精确的=进行查找。如果提供的是一个None,那么在SQL层面就是被解释为NULL。示例代码如下:
article = Article.objects.get(id__exact=14)
article = Article.objects.get(id__exact=None)
以上的两个查找在翻译为SQL语句为如下:
select ... from article where id=14;
select ... from article where id IS NULL;
iexact
在底层会被翻译成LIKE
。示例代码如下:
article = Article.objects.filter(title__iexact='hello world')
那么以上的查询就等价于以下的SQL语句:
select ... from article where title like 'hello world';
- LIKE和=:大部分情况下都是等价的,只有少数情况下是不等价的。
- exict和iexact:他们的区别其实就是LIKE和=的区别,因为exact会被翻译成=,而iexact会被翻译成LIKE。
- 因为
field__exact=xxx
其实等价于filed=xxx
,因此我们直接使用filed=xxx
就可以了,并且因为大部分情况exact
和iexact
又是等价的,因此我们以后直接使用field=xxx
就可以了。
QuerySet.query
QuerySet.query:query
可以用来查看这个ORM
查询语句最终被翻译成的SQL
语句。但是query
只能被用在QuerySet
对象上,不能用在普通的ORM模型
上。因此如果你的查询语句是通过get
来获取数据的,那么就不能使用query
,因为get
返回的是满足条件的ORM
模型,而不是QuerySet
。如果你是通过filter
等其他返回QuerySet
的方法查询的,那么就可以使用query
。
article = Article.objects.filter(title__iexact='hello world') # article是QuerySet对象,所以可以被翻译成sql语句
print(article.query) # 打印sql语句
打印结果
SELECT `article`.`id`, `article`.`title`, `article`.`content`, `article`.`category_id` FROM `article` WHERE `article`.`content` LIKE hello world
contains
大小写敏感,判断某个字段是否包含了某个数据。示例代码如下:
articles = Article.objects.filter(title__contains='hello')
在翻译成SQL语句为如下:
select ... where title like binary '%hello%';
要注意的是,在使用contains
的时候,翻译成的sql语句左右两边是有百分号的,意味着使用的是模糊查询。而exact翻译成sql语句左右两边是没有百分号的,意味着使用的是精确的查询。
icontains
大小写不敏感的匹配查询。示例代码如下:
articles = Article.objects.filter(title__icontains='hello')
翻译成SQL语句为如下:
select ... where title like '%hello%';
in
提取那些给定的field的值是否在给定的容器中。容器可以为list、tuple或者任何一个可以迭代的对象,包括QuerySet
对象。示例代码如下:
articles = Article.objects.filter(id__in=[1,2,3])
也可以通过其他的表的字段来判断是否在某个集合中。示例代码如下:
categories = Category.objects.filter(article__id__in=[1,2,3])
如果要判断相关联的表的字段,那么也是通过__
来连接。并且在做关联查询的时候,不需要写models_set
,直接使用模型的名字的小写化
就可以了。比如通过分类去查找相应的文章,那么通过article__id__in
就可以了,而不是写成article_set__id__in
的形式。当然如果你不想使用默认的形式,可以在外键定义的时候传递related_query_name
来指定反向查询的名字。示例代码如下:
class Category(models.Model):
name = models.CharField(max_length=100)
class Meta:
db_table = 'category'
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
cateogry = models.ForeignKey("Category",on_delete=models.CASCADE,null=True,related_query_name='articles')
class Meta:
db_table = 'article'
因为在cateogry
的ForeignKey
中指定了related_query_name
为articles
,因此你不能再使用article
来进行反向查询了。这时候就需要通过articles__id__in
来进行反向查询。
反向查询和反向引用的区别
- 反向查询:将模型名字小写化。比如
article__in
,就是将Article
模型小写了。当然我们也可以通过related_query_name
来指定自己的方式,而不使用默认的方式。 - 反向引用:将模型名字小写化,然后再加上
_set
,比如article_set
,可以通过related_name
来指定自己的方式,而不是用默认的方式。
并且,如果在做反向查询的时候,如果查询的字段就是模型的主键,那么可以省略掉这个字段,直接写成article__in
就可以了,不需要这个id
了。
in
不仅仅可以指定列表/元组,还可以为QuerySet
。比如要查询“文章标题中包含有hello的所有分类”,那么可以通过以下代码来实现:
articles = Article.objects.filter(title__icontains='hello')
categories = Category.objects.filter(articles__in=articles)
for cateogry in categories:
print(cateogry)
gt
某个field的值要大于给定的值。示例代码如下:
articles = Article.objects.filter(id__gt=3)
以上代码的意思是将所有id大于3的文章全部都找出来。将翻译成以下SQL语句:
select ... where id > 4;
gte
类似于gt,是大于等于。
lt
类似于gt是小于。
lte
类似于lt,是小于等于。
startswith
判断某个字段的值是否是以某个值开始的。大小写敏感。示例代码如下:
articles = Article.objects.filter(title__startswith='hello')
以上代码的意思是提取所有标题以hello字符串开头的文章。将翻译成以下SQL语句:
select ... where title like 'hello%'
istartswith
类似于startswith,但是大小写是不敏感的。
endswith
判断某个字段的值是否以某个值结束。大小写敏感。示例代码如下:
articles = Article.objects.filter(title__endswith='world')
以上代码的意思是提取所有标题以world结尾的文章。将翻译成以下SQL语句:
select ... where title like '%world';
iendswith
类似于endswith,只不过大小写不敏感。
range
判断某个field的值是否在给定的区间中。示例代码如下:
from django.utils.timezone import make_aware
from datetime import datetime
start_time = make_aware(datetime(year=2018, month=1, day=1))
end_time = make_aware(datetime(year=2018, month=12, day=12))
article = Article.objects.filter(create_time__range=(start_time, end_time))
以上代码的意思是提取所有发布时间在2018/1/1到2018/12/12之间的文章。将翻译成以下的SQL语句
select ... from article where pub_time between '2018-01-01' and '2018-12-12'。
注意点
- 以上提取数据,不会包含最后一个值。也就是不会包含2018/12/12的文章。
- 因为我们在
settings.py
中指定了USE_TZ=True
,并且设置了TIME_ZONE='Asia/Shanghai'
,因此我们在提取数据的时候要使用django.utils.timezone.make_aware
先将datetime.datetime
从navie时间转换为aware时间。make_aware
会将指定的时间转换为TIME_ZONE
中指定的时区的时间。
date
针对某些date
或者datetime
类型的字段。可以指定date的范围。并且这个时间过滤,还可以使用链式调用。示例代码如下:
articles = Article.objects.filter(create_time__date=date(2018,3,29))
以上代码的意思是查找时间为2018/3/29这一天发表的所有文章。将翻译成以下的sql语句:
select ... WHERE DATE(CONVERT_TZ(`front_article`.`pub_date`, 'UTC', 'Asia/Shanghai')) = 2018-03-29
注意,因为默认情况下MySQL的表中是没有存储时区相关的信息的。因此我们需要下载一些时区表的文件,然后添加到Mysql的配置路径中。如果你用的是windows
操作系统。那么在http://dev.mysql.com/downloads/timezones.html
下载timezone_2018d_posix.zip - POSIX standard
。然后将下载下来的所有文件拷贝到C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql
中,如果提示文件名重复,那么选择覆盖即可。
如果用的是linux
或者mac
系统,那么在命令行中执行以下命令:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -D mysql -u root -p
,然后输入密码,从系统中加载时区文件更新到mysql中。
year
根据年份进行查找。示例代码如下:
articles = Article.objects.filter(create_time__year=2021)
articles = Article.objects.filter(create_time__year__gte=2021)
以上的代码在翻译成SQL语句为如下:
select ... where pub_date between '2021-01-01' and '2021-12-31';
select ... where pub_date >= '2021-01-01';
month
同year,根据月份进行查找。
day
同year,根据日期进行查找。
week_day
同year,根据星期几进行查找。1表示星期天,7表示星期六,2-6代表的是星期一到星期五。示例代码如下:
article = Article.objects.filter(create_time__week_day=3) # 寻找星期三创建的文章
time
根据时间进行查找。示例代码如下:
articles = Article.objects.filter(create_time__time=datetime.time(12,12,12));
以上的代码是获取每一天中12点12分12秒发表的所有文章。
isnull
根据值是否为空进行查找。示例代码如下:
articles = Article.objects.filter(create_time__isnull=False)
以上的代码的意思是获取所有发布日期不为空的文章。将来翻译成SQL语句如下:
select ... where pub_date is not null;
regex和iregex
大小写敏感和大小写不敏感的正则表达式。示例代码如下:
articles = Article.objects.filter(title__regex=r'^hello')
以上代码的意思是提取所有标题以hello字符串开头的文章。将翻译成以下的SQL语句:
select ... where title regexp binary '^hello';
iregex
是大小写不敏感的。
根据关联的表进行查询
假如现在有两个ORM模型,一个是Article
,一个是Category
。代码如下:
class Category(models.Model):
"""文章分类表"""
name = models.CharField(max_length=100)
class Article(models.Model):
"""文章表"""
title = models.CharField(max_length=100,null=True)
category = models.ForeignKey("Category",on_delete=models.CASCADE)
比如想要获取文章标题中包含"hello"的所有的分类。那么可以通过以下代码来实现:
categories = Category.object.filter(article__title__contains("hello"))
Django(17)orm查询操作的更多相关文章
- Django之ORM查询操作详解
浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Python脚本中调用Django环境 其他操 ...
- Django框架 之 ORM查询操作详解
Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...
- Django【第5篇】:Django之ORM数据库操作
django之ORM数据库操作 一.ORM介绍 映射关系: 表名 -------------------->类名 字段-------------------->属性 表记录-------- ...
- Django的model查询操作 与 查询性能优化
Django的model查询操作 与 查询性能优化 1 如何 在做ORM查询时 查看SQl的执行情况 (1) 最底层的 django.db.connection 在 django shell 中使用 ...
- Django之ORM查询复习与cookie
ORM查询总结: models.Book.objects.filter(**kwargs): querySet [obj1,obj2] models.Book.objects.filter(**kwa ...
- Django之ORM表操作
ORM表操作 1.ORM单表操作 首先想操作表的增删改查,需要先导入这个表,以之前创建的UserInfo表为例,在app下的views.py中导入 from app import models def ...
- Django models ORM基础操作--白话聊Django系列
上次我们讲完了views视图,那我们这次来看一下Django强大的ORM,可以这么说,你不懂Django的ORM,你就不懂Django,那废话不多说 ORM又称关系对象映射,在ORM里,一张表就是一个 ...
- Django ORM 查询操作
queryset中支持链式操作 book=Book.objects.all().order_by('-nid').first() 只要返回的是queryset对象就可以调用其他的方法,直到返回的是对象 ...
- Django orm查询操作
基于双下划线查询切记!!!!正向查询按字段,反向查询按表名的小写 正向:在Book表里设置关联Obj表,Book------>Obj就是正向查询 反向:在Book表里设置关联Obj表,Obj-- ...
随机推荐
- Min25筛求1-n内的素数和
1 //#include <bits/stdc++.h> 2 #include<cstdio> 3 #include<cstring> 4 #include< ...
- windows创建签名文件pfx
https://stackoverflow.com/questions/84847/how-do-i-create-a-self-signed-certificate-for-code-signing ...
- IDA 创建本地类型
在IDA中我们常常使用 shift+F9打开结构体视图,ins 创建结构体,但操作有些繁琐. 我们可以在View-->Open Subviews-->Local Types(视图--> ...
- 攻防世界 reverse serial-150
serial-150 suctf-2016 直接使用ida发现main函数中夹杂大片数据,应该是自修改代码,动态调试: 调试中发现,输入为16位,验证方法为:从头开始取一字符进行比较,比较通过检验后, ...
- 使用命令行编译Qt程序
code[class*="language-"], pre[class*="language-"] { color: rgba(51, 51, 51, 1); ...
- 【linux】驱动-5-驱动框架分层分离&实战
目录 前言 5. 分离分层 5.1 回顾-设备驱动实现 5.2 分离分层 5.3 设备 5.4 驱动 5.5 系统,模块 5.6 Makefile 参考: 前言 5. 分离分层 本章节记录实现LED驱 ...
- $@ 与 $* 差在哪?-- Shell十三问<第九问>
$@ 与 $* 差在哪?-- Shell十三问<第九问> 要说 $@ 与 $* 之前,需得先从 shell script 的 positional parameter 谈起.我们都已经知道 ...
- [BFS]翻币问题
翻币问题 Description 有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止.试编程找出步数最少的翻法, ...
- python基础(二):数据类型
数据类型 学习Python时,一定要注意Python中数据类型和数据结构的学习,这对于你是否能够学好Python其中很重要的作用. 什么是数据类型? 人类有思想,很容易区分汉字和数字的区别,例如,你知 ...
- OOJML系列总结
目录 0x0 JML理论相关 0.0 概念及作用 0.1 JML语法学习 0x1 使用openJml以及JMLUnitNG 1.0 使用openjml 1.1使用JMLUnitNG 0x2 作业架构设 ...