Django查询条件

  • A+
所属分类:ORM

查询操作

查找是数据库操作中一个非常重要的技术。查询一般就是使用filter、exclude以及get三个方法来实现,我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都是使用field+__+connection的方法来实现的。

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;

# 示例(如果是get方法直接返回查询的值,如果是filter则返回QuerySet)
res = qkb.objects.get(cid__exact='5286')
print(res)
5286

注:在Windows操作系统上,mysql的排序规则(collation)无论是什么都是大小写不敏感的;在Linux操作系统上,mysql的排序规则(collation)是utf8_bin那么大小写是敏感的。

iexact

使用like进行查找,示例代码如下:

res = JjYyqkb.objects.filter(cid__iexact='5286')
print(res)
返回:<QuerySet [<qkb: 15004971>]>

上面的查询就等价于下面的SQL语句:

#可以通过下面的res.query返回QuerySet 的查询语句
print(res.query)
select ... from qkb where cid like '5286'

注:上面的SQL语句,因为在MySQL中没有一个叫做ilike的。所以exact和iexact的区别实际上就是like和=的区别,在大部分collation=utf8_general_ci情况下都是一样的(collation是用来对字符串进行比较的)。exact在底层会被翻译成‘=’;iexact在底层会被翻译成‘LIKE’。

contains

大小写敏感的匹配查询,某个字符串是否在指定的字段中。这个判断条件会使用大小写敏感,因此在被翻译成SQL语句的时候,会使用‘like binary’,而‘like binary’就是使用大小写敏感的。示例代码如下:

article = Article.objects.get(title__contains='hello')

在翻译成SQL语句为如下:

select ... from title like binary '%hello%';

注:要注意的是,在使用contains的时候;翻译成的SQL语句左右两边都是有百分号的,意味着使用的是模糊查询。而exact翻译成SQL语句左右两边是没有百分号的,意味着使用的是精确查询。

icontains

大小写不敏感的匹配查询,某个字符串是否被包含在指定的字段中。这个判断条件会不使用大小写敏感,因此在被翻译成SQL语句的时候,会使用‘like’,而‘like’就是不使用大小写敏感的。示例代码如下:

article = Article.objects.get(title__icontains='hello')

在翻译成SQL语句为如下:

select ... from title like '%hello%';

in

提取那些给定的field的值是否在给定的容器中,容器可以为list,tuple或者任何一个可以迭代的对象,包括QuerySet对象。示例代码如下:

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

在翻译成SQL语句为如下:

select ... where id in (1,2,3);

如果要判断相关联的表字段,也可以通过'__'来连接。并且在做反向引用的时候,不需要些'models_set',直接使用模型的名字的小写化就可以了,而不是写成article_set__id__in的形式。当然如果你不想使用默认的形式,可以在外键定义的时候传递'related_query_name'来指定反向引用的名字。示例代码如下:

class Category(model.Model):
    name = models.CharField(max_length=100)
    
    class Meta:
        db_table = 'category'
        
class Article(model.Model)
 title = models.CharField(max_length=200)
    content = models.TextField()
    category = models.ForeignKey("Category",on_delete=models.CASCADE,null=True,related_query_name='articles')
    
    class Meta:
        db_table = 'article'

因为我们在‘category’的‘ForeignKey’中指定了‘related_query_name’为‘articles’,因此我们不能再使用‘article’来进行反向查询了。这时候就需要通过‘article__id__in’来进行反向查询。并且,如果在做反向查询时,查询的字段就是模型的主键,那么可以省略掉这个字段,直接写成'article_in'就可以了。

当然也可以传递一个QuerySet对象进去。in不仅仅可以指定列表/元组,还可以为QuerySet。比如要查询“文章标题中包含有hello”的所有分类,那么就可以通过以下代码来实现。示例代码如下:

inner_qs = Article.objects.filter(title__contains='hello')
categories = Category.objects.filter(article__in=inner_qs)
for category in categories:
    print(category)

上面的代码意思就是获取哪些文章标题包含hello的所有分类。翻译成SQL语句,示例代码如下:

select ... from category where article.id in (select id from article where title like '%hello%');

gt

# 找出大于什么什么的数据
articles = Article.objects.filter(id__gt=2) #查询id大于2的所有数据
print(articles)

gte

# 找出大于等于什么的数据
articles = Article.objects.filter(id__gte=2) #查询id大于等于2的所有数据
print(articles)

lt

# 找出小于什么的数据
articles = Article.objects.filter(id__lt=2) #查询id小于2的所有数据
print(articles)

lte

# 找出小于等什么的数据
articles = Article.objects.filter(id__lte=2) #查询id小于等于2的所有数据
print(articles)

 

startswith

# 以指定某个字符串开始,大小写敏感
# 查询该表下hello为开头的数据,不是hello开头,或者存在大小写的都查询不到
articles = Article.objects.filter(title__startswith='hello')
print(articles)

istartswith

# 以指定某个字符串开始,大小写不敏感
# 查询该表下hello为开头的数据,不是hello开头的查询不到,不在乎大小写
articles = Article.objects.filter(title__istartswith='hello')
print(articles)

endswith

# 查询某个字符串结束的数据,大小写敏感
# 查询该表下hello为结尾的数据,如果存在大写,那就查找不出来
articles = Article.objects.filter(title__endswith='hello') 
print(articles)

iendswith

# 查询某个字符串结束的数据,大小写不敏感
# 查询该表下hello为结尾的数据,忽略大小写
articles = Article.objects.filter(title__iendswith='hello') 
print(articles)

range

判断某个field的值是否在给定的区间内,示例代码如下:

from datetime import datetime
from django.utils.timezone import make_aware

# 获取某个范围内的数据,即相当于between ··· and ···,用小括号和中括号都可以
# 这里以获取某个时间段为例
start_time = make_aware(datetime(year=2019,month=4,day=4,hour=17,minute=0,second=0))
end_time = make_aware(datetime(year=2019,month=4,day=4,hour=18,minute=0,second=0))
articles = Article.objects.filter(create_time__range=(start_time,end_time)) 
print(articles)

上面的代码意思是提取所有发布时间在2019年4月4日17点0分0秒到2019年4月4日18点0分0秒之间的内容。翻译成SQL语句内容如下:

select ... from article where create_time between '2019-04-04 17:00:00' and '2019-04-04 18:00:00'

注:需要注意的是,上面提取的数据不会包含最后一个值。也就是2019-04-04 18:00:00的内容。还有一点需要注意的是,因为我们再setting.py中指定了USE_TZ=True,并且设置了TIME_ZONE='Asia/Shanghai',因此我们在提取数据的时候要使用from django.utils.timezone import make_aware先将datetime从navie时间转换为aware时间。make_aware会将指定的时间转换为TIME_ZONE中指定的时区时间。

date

# 找到符合条件2018-4-4的所有数据
articles = Article.objects.filter(create_time__date=datetime(year=2018,month=4,day=4))  
print(articles)

return HttpResponse('success')16. isnull 判断某个数据是否为空进行查找

snull

# isnull 判断某个数据是否为空进行查找
# 获取该create_time字段下为空的数据
articles = Article.objects.filter(create_time__isnull=True) 
print(articles)

regex

# 使用正则查询数据,大小写敏感
# 获取该title字段下为开头为hell的数据,区分大小写
articles = Article.objects.filter(title__regex=r'^hell') 
print(articles)

iregex

# 使用正则查询数据,不区分大小写
# 获取该title字段下开头为为hell的数据,不区分大小写
articles = Article.objects.filter(title__iregex=r'^hell') 
print(articles)
  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: