Django查询条件

查询操作

查找是数据库操作中一个非常重要的技术。查询一般就是使用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)

推荐文章

13条评论

  1. As I web site possessor I believe the content material here is rattling magnificent , appreciate it for your hard work. You should keep it up forever! Best of luck. Dyane Dav Waterer

  2. Your stories are beautiful and relevant. My thanks for sharing. Selle Skye Schaeffer

  3. I discovered your blog website on google and inspect a few of your early posts. Remain to keep up the excellent operate. I simply extra up your RSS feed to my MSN Information Reader. Looking for onward to learning more from you later on!? Gianina Ryan Hurlee

  4. Hi mates, its impressive piece of writing regarding cultureand entirely explained, keep it up all the time. Charmane Kendall Lolly

  5. thanks for this information, i am searching a long time to realize this. Milissent Hillier Brinna

  6. Thanks for sharing, this is a fantastic blog. Much thanks again. Really Cool. Candis Stanislaw Hakon

  7. Dead indited subject matter, Really enjoyed examining. Emma Kilian Jenine

  8. Keep up the good piece of work, I read few posts on this internet site and I think that your site is rattling interesting and contains circles of excellent info . Shanta Harp Lupien

  9. My brother recommended I might like this blog. He was entirely right. This post truly made my day. You can not imagine simply how much time I had spent for this information! Thanks! Ariella Isidoro Lupien

  10. As I site possessor I believe the content matter here is rattling magnificent , appreciate it for your efforts. You should keep it up forever! Best of luck. Stephanie Kendell Philbert

  11. Sweet blog! I found it while surfing around on Yahoo News. Daffi Park Bainter

  12. magnificent issues altogether, you simply won a new reader. What might you recommend in regards to your publish that you just made a few days in the past? Any sure? Chelsae Brendon Carissa

  13. Perfectly written topic material , thanks for selective details . Josy Erin Nahamas

发表评论

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