Django(17)orm查询操作「建议收藏」

Django(17)orm查询操作「建议收藏」前言查找是数据库操作中一个非常重要的技术。查询一般就是使用filter、exclude以及get三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言

查找是数据库操作中一个非常重要的技术。查询一般就是使用filterexclude以及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就可以了,并且因为大部分情况exactiexact又是等价的,因此我们以后直接使用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'

因为在cateogryForeignKey中指定了related_query_namearticles,因此你不能再使用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"))
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/165043.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 暴力破解(一)——python脚本暴力破解 加密的zip压缩文件

    暴力破解(一)——python脚本暴力破解 加密的zip压缩文件简介:zip格式是常见的压缩文件格式,它支持压缩时设置解压密码;有两种加密方式:1传统加密方式和普通的加密方式。传统加密方式是一种比较简单的加密方式,现在一般很少有人使用,而且压缩时系统默认选择的是普通的加密方式。因此网上很多破解zip的软件和脚本都是针对传统加密方式开发的,所以我们拿来使用时,无法对zip进行破解,所以博主使用python搞了一个针对所有压缩加密方式通用的pytho…

    2022年4月29日
    286
  • Python学习系列:PyCharm CE 安装与测试

    Python学习系列:PyCharm CE 安装与测试开坑啦开坑啦~最近比赛要用Python了,开始强行学习。Mac下PyCharmCE安装先去百度PyCharm,一个很好用IDE,下载免费版的就够用啦:https://www.jetbrains.com/pycharm/然后下载安装,这里就一步步走就好。重点是你的Python,Mac自带的是Python2PyCharm在新建项目的时候会自动识别。测试我们新建一个项目:设置…

    2022年8月29日
    6
  • 软件测试用例常用七大方法

    软件测试用例常用七大方法第一:测试用例格式包括十大特点用例编号测试项测试标题用例属性重要级别:高中低预置条件测试输入操作步骤预期结果实际结果第二:等价类1,等价类定义2,等价类划分3,等价类划分规则4,进行等价类用例设计5,案例加以说明第三:边界值1,边界值的三点2,边界值应用场景3,边界值方法应用步骤第四:判定…

    2022年6月30日
    22
  • FPGA与VHDL_vhdl和verilog

    FPGA与VHDL_vhdl和verilogVHDL相对于VerilogHDL,给人最深刻的印象便是臃肿,掌握起来比较难。本文摘自《FPGA之道》,学会站在巨人的肩膀上来对比学习二者。

    2022年9月21日
    1
  • excel中html批量转化为pdf文件,如何将大量的Excel转换成PDF?

    excel中html批量转化为pdf文件,如何将大量的Excel转换成PDF?大家都知道Excel表,最怕别人修改了,尤其是数据。一旦修改,可能就会有麻烦。那如何是好呢?有一个最简单的办法就是把Excel转换成PDF文件,这样别人只能阅读不能编辑,就不用担心被修改了,哈哈~下面就随小编一起来看下Excel转PDF的办法有哪些吧?方法一:需要一份份文件手动处理。1、创建PDF文件a、打开需转成PDF的文件,譬如本例的表格:成本数据b、单击工具栏上的“文件”标签,点击“保存并发…

    2022年5月18日
    56
  • kfold交叉验证_SPSS交叉验证法

    kfold交叉验证_SPSS交叉验证法一、前言在机器学习建模过程中,通行的做法是将数据分为训练集和测试集。测试集是与训练独立的数据,完全不参与训练,用于最终模型的评估。在训练过程中,经常会出现过拟合的问题,就是模型可以很好的匹配训练数据,却不能很好在预测训练集外的数据。如果此时就使用测试数据来调整模型参数,就相当于在训练时已知部分测试数据的信息,会影响最终评估结果的准确性。通常的做法是在训练数据再中分出一部分做为验证(Validation)数据,用来评估模型的训练效果。验证数据取自训练数据,但不参与训练,这样可以相对客观的评估模型对于训

    2022年9月20日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号