django開發系列:ORM查詢條件詳解
查詢條件:
-
exact:在底層會被翻譯成
=
。 -
iexact:在底層會被翻譯成
LIKE
。- LIKE和=:大部分情況下都是等價的,只有少數情況下是不等價的。
- exict和iexact:他們的區別其實就是LIKE和=的區別,因爲exact會被翻譯成=,而iexact會被翻譯成LIKE。
- 因爲
field__exact=xxx
其實等價於filed=xxx
,因此我們直接使用filed=xxx
就可以了,並且因爲大部分情況exact
和iexact
又是等價的,因此我們以後直接使用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
,而like
在MySQL
層面就是不區分大小寫的。 -
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'
因爲在
cateogry
的ForeignKey
中指定了related_query_name
爲articles
,因此你不能再使用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")
-
關於時間的查詢條件:
-
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
中添加好那些時區文件。如何添加呢?參考教案。示例代碼如下: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))
-