Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關係,它能自動確認 SQL JOIN 聯繫。要作跨關係查詢,就使用兩個下劃線來連接模型(model)間關聯字段的名稱,直到最終連接到你想要的model 爲止。python
核心得學會通知ORM引擎何時,join哪張表mysql
join看似複雜,實則最簡單。由於把字段列出來以後,就至關於單表操做了!想怎麼取值均可以!git
正向查詢按字段,反向查詢按表名小寫用來告訴ORM引擎join哪張表sql
返回值是QuerySet數據庫
返回結構是queryset()django
正向查詢:關聯屬性在book表中,因此book對象找關聯出版社對象,正向查詢
反向查詢:關聯屬性在book表中,因此publish對象找關聯書籍,反向查詢編程
按字段:xx book ------------------ > publish <-------------------- 按表名小寫__字段名。好比publish__name
先使用原生sql查詢app
SELECT app01_publish.name from app01_book INNER JOIN app01_publish on app01_book.publish_id = app01_publish.id WHERE app01_book.title = '西遊記'
執行結果爲:榴蓮出版社ide
它的步驟爲:先連表,再過濾函數
使用orm引擎查詢
修改settings.py,最後一行添加。表示開啓日誌
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'fy', # 要鏈接的數據庫,鏈接前須要建立好 'USER':'root', # 鏈接數據庫的用戶名 'PASSWORD':'123', # 鏈接數據庫的密碼 'HOST':'127.0.0.1',# 鏈接主機,默認本級 'PORT':3306 # 端口 默認3306 } }
修改urls.py,增長路徑query
urlpatterns = [ path('admin/', admin.site.urls), path('add/', views.add), path('query/', views.query), ]
修改views.py,增長query視圖函數
def query(request): ret = Book.objects.filter(title='西遊記').values("publish__name") print(ret)
解釋:
Book.objects 表示基礎表,它是鏈式編程的開始。
publish__name 表示publish表下的name字段。由於要的name字段,它不在Book表中。那麼指定外部表示,須要加雙下劃線。注意:此表必需要和Book表有關聯!
訪問url:http://127.0.0.1:8000/query/
查看Pycharm控制檯,輸出:
<QuerySet [{'publish__name': '榴蓮出版社'}]> (0.000) SELECT "app01_publish"."name" FROM "app01_book" INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_book"."title" = '西遊記' LIMIT 21; args=('西遊記',)
能夠看出,ORM執行的sql和手寫的sql,大體是同樣的!
def query(request): ret = Publish.objects.filter(book__title="西遊記").values("name") print(ret) return HttpResponse('查詢成功')
解釋:
book__title 表示book表中的title字段,它不須要加引號
values("name") 表示publish表的中name字段,爲何呢?由於基礎表示publish,它能夠直接取name字段!
刷新頁面,查看控制檯輸出:
(0.001) SELECT "app01_publish"."name" FROM "app01_publish" INNER JOIN "app01_book" ON ("app01_publish"."id" = "app01_book"."publish_id") WHERE "app01_book"."title" = '西遊記' LIMIT 21; args=('西遊記',) <QuerySet [{'name': '榴蓮出版社'}]>
查詢結果上面的例子是同樣的。
正向查詢:關聯屬性在book表中,因此book對象找關聯做者集合,正向查詢
反向查詢:關聯屬性在book表中,因此author對象找關聯書籍,反向查詢
正 按字段:xx book ------------------------- > author <------------------------- 反 按表名小寫__字段名
先用原生sql查詢
SELECT app01_author.name,app01_author.age from app01_book INNER JOIN app01_book_authors on app01_book_authors.book_id = app01_book.id INNER JOIN app01_author on app01_book_authors.author_id = app01_author.id WHERE app01_book.title = '西遊記'
涉及到3表查詢,查詢結果爲:
使用orm引擎查詢
def query(request): ret = Book.objects.filter(title="西遊記").values("authors__name","authors__age") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'authors__name': 'xiao', 'authors__age': 25}]> (0.001) SELECT "app01_author"."name", "app01_author"."age" FROM "app01_book" LEFT OUTER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") LEFT OUTER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") WHERE "app01_book"."title" = '西遊記' LIMIT 21; args=('西遊記',)
解釋:
因爲book表和author表是多對多關係,因此使用ORM查詢時,它會自動對應關係
authors__name 表示author表的name字段
那麼使用ORM處理多表,就顯得很簡單了!
仍是上面的需求,以author爲基礎表查詢
def query(request): ret = Author.objects.filter(book__title="西遊記").values("name","age") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'name': 'xiao', 'age': 25}]> (0.002) SELECT "app01_author"."name", "app01_author"."age" FROM "app01_author" INNER JOIN "app01_book_authors" ON ("app01_author"."id" = "app01_book_authors"."author_id") INNER JOIN "app01_book" ON ("app01_book_authors"."book_id" = "app01_book"."id") WHERE "app01_book"."title" = '西遊記' LIMIT 21; args=('西遊記',)
執行結果同上!
正向查詢:關聯屬性在authordetail表中,因此author對象找關聯做者詳情,正向查詢
反向查詢:關聯屬性在author表中,因此authordetail對象找關聯做者信息,反向查詢
正向: 按字段:.ad author ------------------------- > authordetail <------------------------- 反向: 按表名小寫 authordetail_obj.author
def query(request): ret = Author.objects.filter(name="xiao").values("ad__gf") print(ret) return HttpResponse('查詢成功')
解釋:ORM查詢時,會自動對應關係。ad__gf表示authordetail表的gf字段
刷新頁面,查看控制檯輸出:
<QuerySet [{'ad__gf': '趙麗穎'}]> (0.001) SELECT "app01_authordetail"."gf" FROM "app01_author" INNER JOIN "app01_authordetail" ON ("app01_author"."ad_id" = "app01_authordetail"."id") WHERE "app01_author"."name" = 'xiao' LIMIT 21; args=('xiao',)
仍是上面的需求,以authordetail表爲基礎表查詢
def query(request): ret = AuthorDetail.objects.filter(author__name="xiao").values("gf") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'gf': '趙麗穎'}]> (0.002) SELECT "app01_authordetail"."gf" FROM "app01_authordetail" INNER JOIN "app01_author" ON ("app01_authordetail"."id" = "app01_author"."ad_id") WHERE "app01_author"."name" = 'xiao' LIMIT 21; args=('xiao',)
def query(request): ret = Book.objects.filter(publish__name="榴蓮出版社").values_list("title","authors__name") print(ret) return HttpResponse('查詢成功')
解釋:
book表示鏈接出版社和做者的核心表。以它爲基礎表查詢,比較好處理!
publish__name 表示publish表的name字段。
authors__name表示book_authors表(book和author的關係表)的name字段。
刷新頁面,查看控制檯輸出:
<QuerySet [('西遊記', 'xiao')]> (0.000) SELECT "app01_book"."title", "app01_author"."name" FROM "app01_book" INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") LEFT OUTER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") LEFT OUTER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") WHERE "app01_publish"."name" = '榴蓮出版社' LIMIT 21; args=('榴蓮出版社',)
仍是上面的需求,以publish表爲基礎表查詢
def query(request): ret = Publish.objects.filter(name="榴蓮出版社").values_list("book__title","book__authors__age","book__authors__name") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [('西遊記', 25, 'xiao')]> (0.001) SELECT "app01_book"."title", "app01_author"."age", "app01_author"."name" FROM "app01_publish" LEFT OUTER JOIN "app01_book" ON ("app01_publish"."id" = "app01_book"."publish_id") LEFT OUTER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") LEFT OUTER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") WHERE "app01_publish"."name" = '榴蓮出版社' LIMIT 21; args=('榴蓮出版社',)
提示:涉及到5表查詢!
先使用原生sql查詢
SELECT app01_book.title,a01p.name from app01_book INNER JOIN app01_book_authors as a on app01_book.id = a.book_id INNER JOIN app01_author as a3 on a.author_id = a3.id INNER JOIN app01_authordetail as a2 on a3.ad_id = a2.id INNER JOIN app01_publish as a01p on app01_book.publish_id = a01p.id WHERE a2.tel like '11%'
執行結果:
使用orm引擎查詢
def query(request): ret = Book.objects.filter(authors__ad__tel__startswith="11").values("title","publish__name") print(ret) return HttpResponse('查詢成功')
解釋:
authors__ad__tel 表示book_authors表,author表的ad字段,authordetail表的tel字段,作關聯查詢。
__startswith 表示以什麼開頭,它會使用like查詢,好比'11%'
"title","publish__name" 分別表示book表的title字段,publish表的name字段
刷新頁面,查看控制檯輸出:
<QuerySet [{'title': 'python', 'publish__name': '西瓜出版社'}, {'title': 'python', 'publish__name': '西瓜出版社'}, {'title': 'python', 'publish__name': '西瓜出版社'}, {'title': '西遊記', 'publish__name': '榴蓮出版社'}, {'title': '三國演義', 'publish__name': '西瓜出版社'}]> (0.001) SELECT "app01_book"."title", "app01_publish"."name" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") INNER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") INNER JOIN "app01_authordetail" ON ("app01_author"."ad_id" = "app01_authordetail"."id") INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_authordetail"."tel" LIKE '11%' ESCAPE '\' LIMIT 21; args=('11%',)
def query(request): ret = Author.objects.filter(ad__tel__startswith="11").values("book__title","book__publish__name") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'book__publish__name': '西瓜出版社', 'book__title': 'python'}, {'book__publish__name': '榴蓮出版社', 'book__title': '西遊記'}, {'book__publish__name': '西瓜出版社', 'book__title': 'python'}, {'book__publish__name': '西瓜出版社', 'book__title': '三國演義'}, {'book__publish__name': '西瓜出版社', 'book__title': 'python'}]> (0.001) SELECT "app01_book"."title", "app01_publish"."name" FROM "app01_author" INNER JOIN "app01_authordetail" ON ("app01_author"."ad_id" = "app01_authordetail"."id") LEFT OUTER JOIN "app01_book_authors" ON ("app01_author"."id" = "app01_book_authors"."author_id") LEFT OUTER JOIN "app01_book" ON ("app01_book_authors"."book_id" = "app01_book"."id") LEFT OUTER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_authordetail"."tel" LIKE '11%' ESCAPE '\' LIMIT 21; args=('11%',)
聚合 是aggreate(*args,**kwargs),經過QuerySet 進行計算。作求值運算的時候使用
主要有Sum,Avg,Max,Min。使用前,須要導入模塊
from django.db.models import Sum,Avg,Max,Min,Count
返回值是一個字典
def query(request): ret = Book.objects.all().aggregate(Sum("price")) print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
{'price__sum': Decimal('522.00')} (0.001) SELECT CAST(SUM("app01_book"."price") AS NUMERIC) AS "price__sum" FROM "app01_book"; args=() [02/Jul/2018 21:45:26] "GET /query/ HTTP/1.1" 200 12
返回值是一個字典
使用原生sql查詢
select avg(price) from app01_book
執行輸出:174
使用orm引擎查詢
def query(request): ret = Book.objects.all().aggregate(Avg("price")) print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
(0.001) SELECT AVG("app01_book"."price") AS "price__avg" FROM "app01_book"; args=() [02/Jul/2018 21:38:42] "GET /query/ HTTP/1.1" 200 12 {'price__avg': 174.0}
aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。若是你想要爲聚合值指定一個名稱,能夠向聚合子句提供它。
def query(request): ret = Book.objects.all().aggregate(avg = Avg("price")) print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
{'avg': 174.0} (0.001) SELECT AVG("app01_book"."price") AS "avg" FROM "app01_book";args=()
def query(request): ret = Book.objects.all().aggregate(count = Count("id")) print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
{'count': 3} (0.001) SELECT COUNT("app01_book"."id") AS "count" FROM "app01_book"; args=()
分組:將查詢結果按照某個字段或多個字段進行分組。字段中值相等的爲一組!
annotate()爲調用的QuerySet中每個對象都生成一個獨立的統計值(統計方法用聚合函數)。
修改models.py,增長一個模型表
class Emp(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() salary=models.DecimalField(max_digits=8,decimal_places=2) dep=models.CharField(max_length=32) province=models.CharField(max_length=32)
使用2個命令生成表
python manage.py makemigrations python manage.py migrate
使用sql插入3條數據,注意修改應用名
INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES (1, 'zhang', 26, 4000, '保潔部', '山東省'); INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES (2, 'li', 25, 3500, '保潔部', '北京'); INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES (3, 'wang', 27, 5000, '公關部', '北京');
使用原生sql查詢
select dep,avg(salary) from app01_emp GROUP BY dep
使用orm引擎查詢
導入emp表
from app01.models import Book,Publish,Author,AuthorDetail,Emp
修改視圖函數
<QuerySet [{'dep': '保潔部', 'avg_salary': 3750.0}, {'dep': '公關部', 'avg_salary': 5000.0}]> (0.000) SELECT "app01_emp"."dep", AVG("app01_emp"."salary") AS "avg_salary" FROM "app01_emp" GROUP BY "app01_emp"."dep" LIMIT 21;args=()
解釋:
values("dep") 表示以dep字段進行分組
avg_salary 表示爲字段起別名
Avg("salary") 表示取平均數
刷新頁面,查看控制檯輸出:
<QuerySet [{'salary__avg': 3750.0, 'dep': '保潔部'}, {'salary__avg': 5000.0, 'dep': '公關部'}]> (0.001) SELECT "app01_emp"."dep", AVG("app01_emp"."salary") AS "salary__avg" FROM "app01_emp" GROUP BY "app01_emp"."dep" LIMIT 21; args=()
def query(request): ret = Emp.objects.values("province").annotate(Count("id")) print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'id__count': 2, 'province': '北京'}, {'id__count': 1, 'province': '山東省'}]> (0.002) SELECT "app01_emp"."province", COUNT("app01_emp"."id") AS "id__count" FROM "app01_emp" GROUP BY "app01_emp"."province" LIMIT 21; args=()
總結:
單表.objects.values('group by 字段').annotate(統計字段)
使用原生sql查詢
select app01_publish.name,avg(app01_book.price) from app01_book INNER JOIN app01_publish ON app01_publish.id = app01_book.publish_id GROUP BY app01_publish.id
查詢結果:
使用orm引擎查詢
def query(request): ret = Publish.objects.values("id").annotate(avg=Avg("book__price")).values("name","avg") print(ret) return HttpResponse('查詢成功')
解釋:
values("id") 以id字段進行分組
avg=Avg("book__price") 表示將關聯的book表的price字段,計算平均數。avg表示起別名
values("name","avg") 取出name和avg字段
刷新頁面,查看控制檯輸出:
<QuerySet [{'name': '西瓜出版社', 'avg': 211.0}, {'name': '榴蓮出版社', 'avg': 100.0}]> (0.000) SELECT "app01_publish"."name", AVG("app01_book"."price") AS "avg" FROM "app01_publish" LEFT OUTER JOIN "app01_book" ON ("app01_publish"."id" = "app01_book"."publish_id") GROUP BY "app01_publish"."id", "app01_publish"."name" LIMIT 21; args=()
def query(request): ret = Book.objects.values("id").annotate(count=Count("authors__name")).values("title","count") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'title': 'python', 'count': 3}, {'title': '三國演義', 'count': 1}, {'title': '西遊記', 'count': 1}]> (0.001) SELECT "app01_book"."title", COUNT("app01_author"."name") AS "count" FROM "app01_book" LEFT OUTER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") LEFT OUTER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") GROUP BY "app01_book"."id", "app01_book"."title" LIMIT 21; args=()
def query(request): ret = Book.objects.values("id").annotate(count=Count("authors__name")).filter(count__gt=1).values("title","count") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [{'title': 'python', 'count': 3}]> (0.001) SELECT "app01_book"."title", COUNT("app01_author"."name") AS "count" FROM "app01_book" LEFT OUTER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") LEFT OUTER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") GROUP BY "app01_book"."id", "app01_book"."title" HAVING COUNT("app01_author"."name") > 1 LIMIT 21;
注意:它使用了HAVING
跨表分組查詢本質就是將關聯表join成一張表,再按單表的思路進行分組查詢。
1 肯定是不是多表分組 2 若是是多表分組,肯定分組條件(group by哪個字段) 3 語法: 每個後跟的表A.objects.values("id").annotate("統計函數(與A表關聯的B表下的某個字段)")
def query(request): ret = Publish.objects.annotate(MinPrice=Min("book__price")).values_list("name","MinPrice") print(ret) return HttpResponse('查詢成功')
刷新頁面,查看控制檯輸出:
<QuerySet [('西瓜出版社', Decimal('122.00')), ('榴蓮出版社', Decimal('100.00'))]> (0.001) SELECT "app01_publish"."name", CAST(MIN("app01_book"."price") AS NUMERIC) AS "MinPrice" FROM "app01_publish" LEFT OUTER JOIN "app01_book" ON ("app01_publish"."id" = "app01_book"."publish_id") GROUP BY "app01_publish"."id", "app01_publish"."name", "app01_publish"."email", "app01_publish"."addr" LIMIT 21; args=()
def query(request): ret = Book.objects.annotate(authorsNum=Count('authors__name')).values() print(ret) return HttpResponse('查詢成功')
def query(request): ret = Book.objects.filter(title__startswith="Py").annotate(num_authors=Count('authors')) print(ret) return HttpResponse('查詢成功')
def query(request): ret = Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors').values() print(ret) return HttpResponse('查詢成功')
def query(request): ret = Author.objects.annotate(SumPrice=Sum("book__price")).values("name","SumPrice") print(ret) return HttpResponse('查詢成功')
F()容許Django在未實際連接數據的狀況下具備對數據庫字段的值的引用。一般狀況下咱們在更新數據時須要先從數據庫裏將原數據取出後方在內存裏,而後編輯某些屬性,最後提交。
在上面全部的例子中,咱們構造的過濾器都只是將字段值與某個常量作比較。若是咱們要對兩個字段的值作比較,那該怎麼作呢?
Django 提供 F() 來作這樣的比較。F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。
修改models.py,增長3個字段
class Book(models.Model): title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True) pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) authors=models.ManyToManyField(to="Author") comment_count=models.IntegerField(default=0) up_count=models.IntegerField(default=0) read_count = models.IntegerField(default=0)
使用2個命令生成表
python manage.py makemigrations python manage.py migrate
使用sql語句更新數據,注意:修改應用名
UPDATE app01_book SET comment_count=123, read_count=1231, up_count=2 WHERE id=1; UPDATE app01_book SET comment_count=231, read_count=132, up_count=33 WHERE id=2; UPDATE app01_book SET comment_count=332,read_count=132, up_count=12 WHERE id=3;
常規寫法是不能執行的
ret = Book.objects.filter(comment_count__gt=read_count)
使用F查詢,須要導入模塊
from django.db.models import F
而後使用F查詢
def query(request): ret = Book.objects.filter(comment_count__gt=F("read_count")).values("title") print(ret) return HttpResponse('查詢成功')
Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。
def query(request): ret = Book.objects.filter(comment_count__gt=F('up_count')*2).values("title") print(ret) return HttpResponse('查詢成功')
解釋:
comment_count 表示評論字段
__gt 表示大於
__lt 表示小於
修改操做也可使用F函數
舉例:將每一本書的價格提升30元
def query(request): Book.objects.all().update(price=F("price")+30) # 更新 ret = Book.objects.all().values("title","price") #查詢 print(ret) return HttpResponse('查詢成功')
Q對象(django.db.models.Q)能夠對關鍵字參數進行封裝,從而更好地應用多個查詢。能夠組合使用 &(and),(or),~(not)操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象。
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR 語句),你可使用Q 對象。
使用Q查詢,須要導入模塊
from django.db.models import Q
Q 對象可使用& 和| 操做符組合起來。當一個操做符在兩個Q 對象上使用時,它產生一個新的Q 對象。
def query(request): ret = Book.objects.filter(Q(authors__name="xiao")|Q(authors__name="zhang")).values("title") print(ret) return HttpResponse('查詢成功')
等同於下面的SQL WHERE 子句:
WHERE name ="xiao" OR name ="zhang"
你能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢:
舉例:查詢做者xiao不在2017出版過的全部書籍
def query(request): ret = Book.objects.filter(Q(authors__name="xiao") & ~Q(pub_date__year=2017)).values("title") print(ret) return HttpResponse('查詢成功')
等同於下面的where語句
WHERE ("app01_author"."name" = 'xiao' AND NOT ("app01_book"."pub_date" BETWEEN '2017-01-01' AND '2017-12-31'))
查詢函數能夠混合使用Q 對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。
舉例:查詢書籍名稱中包含 "python",且python不區分大小寫。在2012年或者2017年是否出版過
def query(request): ret = Book.objects.filter(Q(pub_date__year=2012) | Q(pub_date__year=2017),title__icontains="python").values("title") print(ret) return HttpResponse('查詢成功')