Django ORM 常见查询条件

常见查询条件:

  • exact:在底层会被翻译成=

  • iexact:在底层会被翻译成LIKE

    • LIKE和=:大部分情况下都是等价的,只有少数情况下是不等价的。
    • exict和iexact:他们的区别其实就是LIKE和=的区别,因为exact会被翻译成=,而iexact会被翻译成LIKE。
    • 因为field__exact=xxx其实等价于filed=xxx,因此我们直接使用filed=xxx就可以了,并且因为大部分情况exactiexact又是等价的,因此我们以后直接使用field=xxx就可以了。
  • QuerySet.query:query可以用来查看这个ORM查询语句最终被翻译成的SQL语句。但是query只能被用在QuerySet对象上,不能用在普通的ORM模型上。因此如果你的查询语句是通过get来获取数据的,那么就不能使用query,因为get返回的是满足条件的ORM模型,而不是QuerySet。如果你是通过filter等其他返回QuerySet的方法查询的,那么就可以使用query

  • contains:使用大小写敏感的判断,某个字符串是否在指定的字段中。这个判断条件会使用大小敏感,因此在被翻译成SQL语句的时候,会使用like binary,而like binary就是使用大小写敏感的。

  • icontains:使用大小写不敏感的判断,某个字符串是否被包含在指定的字段中。这个查询语句在被翻译成SQL的时候,使用的是like,而likeMySQL层面就是不区分大小写的。

  • contains和icontains:在被翻译成SQL的时候使用的是%hello%,就是只要整个字符串中出现了hello都能过够被找到,而iexact没有百分号,那么意味着只有完全相等的时候才会被匹配到。

  • in:可以直接指定某个字段的是否在某个集合中。例:

    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。可以通过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、gte、lt、lte:代表的是大于、大于等于、小于、小于等于的条件。例:

    articles = Article.objects.filter(id__lte=3)
    
  • startswith、istartswith、endswith、iendswith:表示以某个值开始,不区分大小写的以某个值开始、以某个值结束、不区分大小写的以某个值结束。例:

    articles = Article.objects.filter(title__endswith="hello")
    
  • isnull:根据值是否为空进行查找

    articles = Article.objects.filter(pub_date__isnull=False)
    

    以上的代码的意思是获取所有发布日期不为空的文章。

  • regex和iregex:大小写敏感和大小写不敏感的正则表达式

    articles = Article.objects.filter(title__regex=r'^hello')
    

    以上代码的意思是提取所有标题以hello字符串开头的文章。

    iregex是大小写不敏感的。

关于时间的查询条件:

  • range:可以指定一个时间段。并且时间应该标记为aware时间,不然django会报警告。例:

    start_time = make_aware(datetime(year=2018,month=4,day=4,hour=17,minute=0,second=0))
    end_time = make_aware(datetime(year=2018,month=4,day=4,hour=18,minute=0,second=0))
    articles = Article.objects.filter(create_time__range=(start_time,end_time))
    print(articles.query)
    print(articles)
    
  • date:用年月日来进行过滤。如果想要使用这个过滤条件,那么前提必须要在MySQL中添加好那些时区文件。

    • 因为默认情况下MySQL的表中是没有存储时区相关的信息的。因此我们需要下载一些时区表的文件,然后添加到Mysql的配置路径中。
    • windows操作系统
      • http://dev.mysql.com/downloads/timezones.html 下载timezone_2018d_posix.zip - POSIX standard。
      • 然后将下载下来的所有文件拷贝到C:ProgramDataMySQLMySQL Server 5.7Datamysql中,如果提示文件名重复,那么选择覆盖即可。
    • linux或者mac系统,
      • 那么在命令行中执行以下命令:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -D mysql -u root -p

      • 然后输入密码,从系统中加载时区文件更新到Mysql中。

        例:

        articles = Article.objects.filter(create_time__date=datetime(year=2018,month=4,day=4))
        
  • year/month/day:表示根据年/月/日进行查找。例:

    articles = Article.objects.filter(create_time__year__gte=2018)
    
  • week_day:根据星期来进行查找。1表示星期天,7表示星期六,2-6代表的是星期一到星期五。比如要查找星期三的所有文章,那么可以通过以下代码来实现:

    articles = Article.objects.filter(create_time__week_day=4)
    
  • time:根据分时秒来进行查找。如果要具体到秒,一般比较难匹配到,可以使用区间的方式来进行查找。区间使用range条件。比如想要获取17时/10分/27-28秒之间的文章,那么可以通过以下代码来实现:

    start_time = time(hour=17,minute=10,second=27)
    end_time = time(hour=17,minute=10,second=28)
    articles = Article.objects.filter(create_time__time__range=(start_time,end_time))
    

根据关联的表进行查询:

假如现在有两个ORM模型,一个是Article,一个是Category。代码如下:
python 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://www.cnblogs.com/aduner/p/13546413.html