實例:咱們來假定下面這些概念,字段和關係php
做者模型:一個做者有姓名和年齡。java
做者詳細模型:把做者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。做者詳情模型和做者模型之間是一對一的關係(one-to-one)python
出版商模型:出版商有名稱,所在城市以及email。git
書籍模型: 書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many);一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many)。sql
Book
id title price publish
php 100 人民出版社
python 200 老男孩出版社
go 100 人民出版社
java 300 人民出版社
爲了存儲出版社的郵箱,地址,在第一個表後面加字段
Book
id title price publish email addr
php 100 人民出版社 111 北京
python 200 老男孩出版社 222 上海
go 100 人民出版社 111 北京
java 300 人民出版社 111 北京
這樣會有大量重複的數據,浪費空間
####################################################################################
一對多:一個出版社對應多本書(關聯信息建在多的一方,也就是book表中)
Book
id title price publish_id
php 100 1
python 200 1
go 100 2
java 300 1
Publish
id name email addr
人民出版社 111 北京
沙河出版社 222 沙河
總結:一旦肯定表關係是一對多:在多對應的表中建立關聯字段(在多的表裏建立關聯字段) ,publish_id
查詢python這本書的出版社的郵箱(子查詢)
select publish_id from Book where title=「python」
select email from Publish where id=1
####################################################################################
多對多:一本書有多個做者,一個做者出多本書
Book
id title price publish_id
php 100 1
python 200 1
go 100 2
java 300 1
Author
id name age addr
alex 34 beijing
egon 55 nanjing
Book2Author
id book_id author_id
2 1
2 2
3 2
總結:一旦肯定表關係是多對多:建立第三張關係表(建立中間表,中間表就三個字段,本身的id,書籍id和做者id) :
id book_id author_id
# alex出版過的書籍名稱(子查詢)
select id from Author where name='alex'
select book_id from Book2Author where author_id=1
select title from Book where id =book_id
####################################################################################
一對一:對做者詳細信息的擴展(做者表和做者詳情表)
Author
id name age ad_id(UNIQUE)
alex 34 1
egon 55 2
AuthorDetail
id addr gender tel gf_name author_id(UNIQUE)
beijing male 110 小花 1
nanjing male 911 槓娘 2
總結: 一旦肯定是一對一的關係:在兩張表中的任意一張表中創建關聯字段+Unique
====================================
Publish
Book
Author
AuthorDetail
Book2Author
CREATE TABLE publish(
id INT PRIMARY KEY auto_increment ,
name VARCHAR (20)
);
CREATE TABLE book(
id INT PRIMARY KEY auto_increment ,
title VARCHAR (20),
price DECIMAL (8,2),
pub_date DATE ,
publish_id INT ,
FOREIGN KEY (publish_id) REFERENCES publish(id)
);
CREATE TABLE authordetail(
id INT PRIMARY KEY auto_increment ,
tel VARCHAR (20)
);
CREATE TABLE author(
id INT PRIMARY KEY auto_increment ,
name VARCHAR (20),
age INT,
authordetail_id INT UNIQUE ,
FOREIGN KEY (authordetail_id) REFERENCES authordetail(id)
);
CREATE TABLE book2author(
id INT PRIMARY KEY auto_increment ,
book_id INT ,
author_id INT ,
FOREIGN KEY (book_id) REFERENCES book(id),
FOREIGN KEY (author_id) REFERENCES author(id)
)
分析以下
注意:關聯字段與外鍵約束沒有必然的聯繫(建管理字段是爲了進行查詢,建約束是爲了避免出現髒數據)數據庫
在Models建立以下模型django
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField()
# 閱讀數
# reat_num=models.IntegerField(default=0)
# 評論數
# commit_num=models.IntegerField(default=0)
publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
authors=models.ManyToManyField(to='Author')
def __str__(self):
return self.name
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)
class AuthorDatail(models.Model):
nid = models.AutoField(primary_key=True)
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64)
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
注意事項:app
myapp_modelName
,是根據 模型中的元數據自動生成的,也能夠覆寫爲別的名稱 id
字段是自動添加的CREATE TABLE
SQL 語句使用PostgreSQL 語法格式,要注意的是Django 會根據settings 中指定的數據庫類型來使用相應的SQL 語句。models.py
所在應用的名稱。
方式1: publish_obj=Publish.objects.get(nid=1) book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish=publish_obj) 方式2: book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish_id=1)
核心:book_obj.publish與book_obj.publish_id是什麼? ide
關鍵點:
一 book_obj.publish=Publish.objects.filter(id=book_obj.publish_id).first()
二 book_obj.authors.all()
關鍵點:book.authors.all() # 與這本書關聯的做者集合
1 book.id=3
2 book_authors
id book_id author_ID
3 3 1
4 3 2
3 author
id name
1 alex
2 egon
book_obj.authors.all() -------> [alex,egon]
# -----一對多添加
pub=Publish.objects.create(name='egon出版社',email='445676@qq.com',city='山東')
print(pub)
# 爲book表綁定和publish的關係
import datetime,time
now=datetime.datetime.now().__str__()
now = datetime.datetime.now().strftime('%Y-%m-%d')
print(type(now))
print(now)
# 日期類型必須是日期對象或者字符串形式的2018-09-12(2018-9-12),其它形式不行
Book.objects.create(name='海燕3',price=333.123,publish_date=now,publish_id=2)
Book.objects.create(name='海3燕3',price=35.123,publish_date='2018/02/28',publish=pub)
pub=Publish.objects.filter(nid=1).first()
book=Book.objects.create(name='測試書籍',price=33,publish_date='2018-7-28',publish=pub)
print(book.publish.name)
# 查詢出版了紅樓夢這本書出版社的郵箱
book=Book.objects.filter(name='紅樓夢').first()
print(book.publish.email)
# 當前生成的書籍對象
book_obj=Book.objects.create(title="追風箏的人",price=200,publishDate="2012-11-12",publish_id=1)
# 爲書籍綁定的作做者對象
yuan=Author.objects.filter(name="yuan").first() # 在Author表中主鍵爲2的紀錄
egon=Author.objects.filter(name="alex").first() # 在Author表中主鍵爲1的紀錄
# 綁定多對多關係,即向關係表book_authors中添加紀錄
book_obj.authors.add(yuan,egon) # 將某些特定的 model 對象添加到被關聯對象集合中。 ======= book_obj.authors.add(*[])
book = Book.objects.filter(name='紅樓夢').first()
egon=Author.objects.filter(name='egon').first()
lqz=Author.objects.filter(name='lqz').first()
# 1 沒有返回值,直接傳對象
book.authors.add(lqz,egon)
# 2 直接傳做者id
book.authors.add(1,3)
# 3 直接傳列表,會打散
book.authors.add(*[1,2])
# 解除多對多關係
book = Book.objects.filter(name='紅樓夢').first()
# 1 傳做者id
book.authors.remove(1)
# 2 傳做者對象
egon = Author.objects.filter(name='egon').first()
book.authors.remove(egon)
#3 傳*列表
book.authors.remove(*[1,2])
#4 刪除全部
book.authors.clear()
# 5 拿到與 這本書關聯的全部做者,結果是queryset對象,做者列表
ret=book.authors.all()
# print(ret)
# 6 queryset對象,又能夠繼續點(查詢紅樓夢這本書全部做者的名字)
ret=book.authors.all().values('name')
print(ret)
# 以上總結:
# (1)
# book=Book.objects.filter(name='紅樓夢').first()
# print(book)
# 在點publish的時候,其實就是拿着publish_id又去app01_publish這個表裏查數據了
# print(book.publish)
# (2)book.authors.all()
核心:book_obj.authors.all()是什麼?函數
多對多關係其它經常使用API:
book_obj.authors.remove() # 將某個特定的對象從被關聯對象集合中去除。 ====== book_obj.authors.remove(*[]) book_obj.authors.clear() #清空被關聯對象集合 book_obj.authors.set() #先清空再設置
正向查詢(按字段:publish)
# 查詢主鍵爲1的書籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主鍵爲1的書籍對象關聯的出版社對象
print(book_obj.publish.city)
反向查詢(按表名:book_set)
publish=Publish.objects.get(name="蘋果出版社")
#publish.book_set.all() : 與蘋果出版社關聯的全部書籍對象集合
book_list=publish.book_set.all()
for book_obj in book_list:
print(book_obj.title)
# 一對多正向查詢
book=Book.objects.filter(name='紅樓夢').first()
print(book.publish)#與這本書關聯的出版社對象
print(book.publish.name)
# 一對多反向查詢
# 人民出版社出版過的書籍名稱
pub=Publish.objects.filter(name='人民出版社').first()
ret=pub.book_set.all()
print(ret)
正向查詢(按字段:authorDetail):
egon=Author.objects.filter(name="egon").first() print(egon.authorDetail.telephone)
反向查詢(按表名:author):
# 查詢全部住址在北京的做者的姓名 authorDetail_list=AuthorDetail.objects.filter(addr="beijing") for obj in authorDetail_list: print(obj.author.name)
# 一對一正向查詢
# lqz的手機號
lqz=Author.objects.filter(name='lqz').first()
tel=lqz.author_detail.telephone
print(tel)
# 一對一反向查詢
# 地址在北京的做者姓名
author_detail=AuthorDatail.objects.filter(addr='北京').first()
name=author_detail.author.name
print(name)
正向查詢(按字段:authors):
# 眉全部做者的名字以及手機號
book_obj=Book.objects.filter(title="眉").first()
authors=book_obj.authors.all()
for author_obj in authors:
print(author_obj.name,author_obj.authorDetail.telephone)
反向查詢(按表名:book_set):
# 查詢egon出過的全部書籍的名字
author_obj=Author.objects.get(name="egon")
book_list=author_obj.book_set.all() #與egon做者相關的全部書籍
for book_obj in book_list:
print(book_obj.title)
# 正向查詢----查詢紅樓夢全部做者名稱
book=Book.objects.filter(name='紅樓夢').first()
ret=book.authors.all()
print(ret)
for auth in ret:
print(auth.name)
# 反向查詢 查詢lqz這個做者寫的全部書
author=Author.objects.filter(name='lqz').first()
ret=author.book_set.all()
print(ret)
注意:
你能夠經過在 ForeignKey() 和ManyToManyField的定義中設置 related_name 的值來覆寫 FOO_set 的名稱。例如,若是 Article model 中作一下更改:
publish
=
ForeignKey(Book, related_name
=
'bookList'
)
那麼接下來就會如咱們看到這般:
# 查詢 人民出版社出版過的全部書籍
publish
=
Publish.objects.get(name
=
"人民出版社"
)
book_list
=
publish.bookList.
all
()
# 與人民出版社關聯的全部書籍對象集合
Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關係,它能自動確認 SQL JOIN 聯繫。要作跨關係查詢,就使用兩個下劃線來連接模型(model)間關聯字段的名稱,直到最終連接到你想要的model 爲止。
正向查詢按字段,反向查詢按表名小寫用來告訴ORM引擎join哪張表
# 練習: 查詢蘋果出版社出版過的全部書籍的名字與價格(一對多)
# 正向查詢 按字段:publish
queryResult=Book.objects
.filter(publish__name="蘋果出版社")
.values_list("title","price")
# 反向查詢 按表名:book
queryResult=Publish.objects
.filter(name="蘋果出版社")
.values_list("book__title","book__price")
查詢的本質同樣,就是select from的表不同
# 正向查詢按字段,反向查詢按表名小寫
# 查詢紅樓夢這本書出版社的名字
# select * from app01_book inner join app01_publish
# on app01_book.publish_id=app01_publish.nid
ret=Book.objects.filter(name='紅樓夢').values('publish__name')
print(ret)
ret=Publish.objects.filter(book__name='紅樓夢').values('name')
print(ret)
# 練習: 查詢alex出過的全部書籍的名字(多對多)
# 正向查詢 按字段:authors:
queryResult=Book.objects
.filter(authors__name="yuan")
.values_list("title")
# 反向查詢 按表名:book
queryResult=Author.objects
.filter(name="yuan")
.values_list("book__title","book__price")
# 正向查詢按字段,反向查詢按表名小寫
# 查詢紅樓夢這本書出版社的名字
# select * from app01_book inner join app01_publish
# on app01_book.publish_id=app01_publish.nid
ret=Book.objects.filter(name='紅樓夢').values('publish__name')
print(ret)
ret=Publish.objects.filter(book__name='紅樓夢').values('name')
print(ret)
# sql 語句就是from的表不同
# -------多對多正向查詢
# 查詢紅樓夢全部的做者
ret=Book.objects.filter(name='紅樓夢').values('authors__name')
print(ret)
# ---多對多反向查詢
ret=Author.objects.filter(book__name='紅樓夢').values('name')
ret=Author.objects.filter(book__name='紅樓夢').values('name','author_detail__addr')
print(ret)
# 查詢alex的手機號 # 正向查詢 ret=Author.objects.filter(name="alex").values("authordetail__telephone") # 反向查詢 ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
# 查詢lqz的手機號
# 正向查
ret=Author.objects.filter(name='lqz').values('author_detail__telephone')
print(ret)
# 反向查
ret= AuthorDatail.objects.filter(author__name='lqz').values('telephone')
print(ret)
# 練習: 查詢人民出版社出版過的全部書籍的名字以及做者的姓名
# 正向查詢
queryResult=Book.objects
.filter(publish__name="人民出版社")
.values_list("title","authors__name")
# 反向查詢
queryResult=Publish.objects
.filter(name="人民出版社")
.values_list("book__title","book__authors__age","book__authors__name")
# 練習: 手機號以151開頭的做者出版過的全部書籍名稱以及出版社名稱
# 方式1:
queryResult=Book.objects
.filter(authors__authorDetail__telephone__regex="151")
.values_list("title","publish__name")
# 方式2:
ret=Author.objects
.filter(authordetail__telephone__startswith="151")
.values("book__title","book__publish__name")
# ----進階練習,連續跨表
# 查詢手機號以33開頭的做者出版過的書籍名稱以及書籍出版社名稱
# author_datail author book publish
# 基於authorDatail表
ret=AuthorDatail.objects.filter(telephone__startswith='33').values('author__book__name','author__book__publish__name')
print(ret)
# 基於Author表
ret=Author.objects.filter(author_detail__telephone__startswith=33).values('book__name','book__publish__name')
print(ret)
# 基於Book表
ret=Book.objects.filter(authors__author_detail__telephone__startswith='33').values('name','publish__name')
print(ret)
# 基於Publish表
ret=Publish.objects.filter(book__authors__author_detail__telephone__startswith='33').values('book__name','name')
print(ret)
publish = ForeignKey(Blog, related_name='bookList')
反向查詢時,若是定義了related_name ,則用related_name替換表名,例如:
# 練習: 查詢人民出版社出版過的全部書籍的名字與價格(一對多)
# 反向查詢 再也不按表名:book,而是related_name:bookList
queryResult=Publish.objects
.filter(name="人民出版社")
.values_list("bookList__title","bookList__price")
aggregate(*args, **kwargs)
# 計算全部圖書的平均價格
>>>
from
django.db.models
import
Avg
>>> Book.objects.
all
().aggregate(Avg(
'price'
))
{
'price__avg'
:
34.35
}
>>> Book.objects.aggregate(average_price
=
Avg(
'price'
))
{
'average_price'
:
34.35
}
>>>
from
django.db.models
import
Avg,
Max
,
Min
>>> Book.objects.aggregate(Avg(
'price'
),
Max
(
'price'
),
Min
(
'price'
))
{
'price__avg'
:
34.35
,
'price__max'
: Decimal(
'81.20'
),
'price__min'
: Decimal(
'12.99'
)}
# 查詢全部書籍的平均價格
from django.db.models import Avg,Count,Max,Min
ret=Book.objects.all().aggregate(Avg('price'))
# {'price__avg': 202.896}
# 能夠更名字
ret=Book.objects.all().aggregate(avg_price=Avg('price'))
# 統計平均價格和最大價格
ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))
# 統計最小价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))
# 統計個數和平均價格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))
print(ret)
###################################--單表分組查詢--#######################################################
查詢每個部門名稱以及對應的員工數
emp:
id name age salary dep
alex 12 2000 銷售部
egon 22 3000 人事部
wen 22 5000 人事部
sql語句:
select dep,Count(*) from emp group by dep;
ORM:
emp.objects.values("dep").annotate(c=Count("id")
# 示例:查詢每個部門的名稱,以及平均薪水
# select dep,Avg(salary) from app01_emp group by dep
from django.db.models import Avg, Count, Max, Min
# ret=Emp.objects.values('dep').annotate(Avg('salary'))
# 從新命名
ret=Emp.objects.values('dep').annotate(avg_salary=Avg('salary'))
print(ret)
總結:單表分組查詢orm語法:單表模型.objects.values('group by 的字段').annotate(聚合函數('統計的字段'))
查詢每個省份名稱以及對應的員工數
Emp.objects.values('province').annotate(Count('id'))
###################################--多表分組查詢--###########################
Book表
id title date price publish_id
紅樓夢 2012-12-12 101 1
西遊記 2012-12-12 101 1
三國演繹 2012-12-12 101 1
金梅 2012-12-12 301 2
Publish表
id name addr email
人民出版社 北京 123@qq.com
南京出版社 南京 345@163.com
多表分組查詢:
查詢每一個出版社出版的書籍個數
ret=Book.objects.values('publish_id').annotate(Count('nid'))
print(ret)
查詢每一個出版社的名稱和書籍個數(先join,再分組)
SELECT app01_publish.name,COUNT(app01_book.name) from app01_book
INNER JOIN app01_publish
on app01_publish.nid = app01_book.publish_id
GROUP BY app01_publish.nid
orm實現:
ret=Publish.objects.values('name').annotate(Count('book__name'))
ret=Publish.objects.values('nid').annotate(c=Count('book__name')).values('name','c')
print(ret)
模型總結:跨表查詢的模型:每個後表模型.objects.value('pk').annotate(聚合函數('關聯表__統計字段')).values()
# 查詢每一個做者的名字,以及出版過書籍的最高價格
ret=Author.objects.values('pk').annotate(c=Max('book__price')).values('name','c')
print(ret)
# 查詢每個書籍的名稱,以及對應的做者個數
ret=Book.objects.values('pk').annotate(c=Count('authors__name')).values('name','c')
print(ret)
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)
annotate()爲調用的QuerySet中每個對象都生成一個獨立的統計值(統計方法用聚合函數)。
總結 :跨表分組查詢本質就是將關聯表join成一張表,再按單表的思路進行分組查詢。
(1) 練習:統計每個出版社的最便宜的書
publishList
=
Publish.objects.annotate(MinPrice
=
Min
(
"book__price"
))
for
publish_obj
in
publishList:
print
(publish_obj.name,publish_obj.MinPrice)
queryResult= Publish.objects .annotate(MinPrice=Min("book__price")) .values_list("name","MinPrice") print(queryResult)
ret=Book.objects.annotate(authorsNum=Count('authors__name'))
(3) 統計每一本以py開頭的書籍的做者個數:
queryResult=Book.objects
.filter(title__startswith="Py")
.annotate(num_authors=Count('authors'))
(4) 統計不止一個做者的圖書:
queryResult=Book.objects
.annotate(num_authors=Count('authors'))
.filter(num_authors__gt=1)
(5) 根據一本圖書做者數量的多少對查詢集 QuerySet進行排序:
Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
(6) 查詢各個做者出的書的總價格:
# 按author表的全部字段 group by
queryResult=Author.objects
.annotate(SumPrice=Sum("book__price"))
.values_list("name","SumPrice")
print(queryResult)
# ————————————單表下的分組查詢
'''
查詢每個部門名稱以及對應的員工數
emp:
id name age salary dep
1 alex 12 2000 銷售部
2 egon 22 3000 人事部
3 wen 22 5000 人事部
'''
# select count(id) from emp group by dep
# 示例一:查詢每個部門的名稱,以及平均薪水
# select dep,Avg(salary) from app01_emp group by dep
from django.db.models import Avg, Count, Max, Min
ret=Emp.objects.values('dep').annotate(Avg('salary'))
# 從新命名
ret=Emp.objects.values('dep').annotate(avg_salary=Avg('salary'))
print(ret)
# ---*******單表分組查詢ORM總結:表名.objects.values('group by 的字段').annotate(聚合函數('統計的字段'))
# 示例2 查詢每一個省份對應的員工數
ret=Emp.objects.values('province').annotate(Count('id'))
ret=Emp.objects.values('province').annotate(c=Count('id'))
print(ret)
# 補充知識點:
ret=Emp.objects.all()
# select * from emp
ret=Emp.objects.values('name')
# select name from emp
# ****單表下,按照id進行分組是沒有任何意義的
ret=Emp.objects.all().annotate(Avg('salary'))
print(ret)
# ******多表分組查詢
# 查詢每個出版社出版的書籍個數
ret=Book.objects.values('publish_id').annotate(Count('nid'))
print(ret)
# 查詢每一個出版社的名稱以及出版社書的個數(先join在跨表分組)
# 正向
ret=Publish.objects.values('name').annotate(Count('book__name'))
ret=Publish.objects.values('nid').annotate(c=Count('book__name')).values('name','c')
print(ret)
# 反向
ret=Book.objects.values('publish__name').annotate(Count('name'))
ret=Book.objects.values('publish__name').annotate(c=Count('name')).values('publish__name','c')
print(ret)
# 查詢每一個做者的名字,以及出版過書籍的最高價格
ret=Author.objects.values('pk').annotate(c=Max('book__price')).values('name','c')
print(ret)
# 跨表查詢的模型:每個後表模型.objects.value('pk').annotate(聚合函數('關聯表__統計字段')).values()
# 查詢每個書籍的名稱,以及對應的做者個數
ret=Book.objects.values('pk').annotate(c=Count('authors__name')).values('name','c')
print(ret)
# 統計不止一個做者的圖書
ret=Book.objects.values('pk').annotate(c=Count('authors__name')).filter(c__gt=1).values('name','c')
print(ret)
在上面全部的例子中,咱們構造的過濾器都只是將字段值與某個常量作比較。若是咱們要對兩個字段的值作比較,那該怎麼作呢?
Django 提供 F() 來作這樣的比較。F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。
# 查詢評論數大於收藏數的書籍
from django.db.models import F
Book.objects.filter(commnetNum__lt=F('keepNum'))
Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。
# 查詢評論數大於收藏數2倍的書籍
Book.objects.filter(commnetNum__lt=F('keepNum')*2)
修改操做也可使用F函數,好比將每一本書的價格提升30元:
Book.objects.all().update(price=F("price")+30)
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR 語句),你可使用Q 對象。
from django.db.models import Q
Q(title__startswith='Py')
Q 對象可使用& 和| 操做符組合起來。當一個操做符在兩個Q 對象上使用時,它產生一個新的Q 對象。
bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))
等同於下面的SQL WHERE 子句:
WHERE name
=
"yuan"
OR name
=
"egon"
你能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢:
bookList=Book.objects.filter(Q(authors__name="yuan") & ~Q(publishDate__year=2017)).values_list("title")
查詢函數能夠混合使用Q 對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。例如:
bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
title__icontains="python"
)
# 查詢評論數大於閱讀數的書籍
from django.db.models import F,Q
# select * from book where commit_num>read_num;
# 這樣確定是不行的
# Book.objects.filter(commit_num__gt=read_num)
ret=Book.objects.filter(commit_num__gt=F('reat_num'))
print(ret)
# 把全部書籍的價格加10
Book.objects.all().update(price=F('price')+10)
# ----Q函數,描述一個與,或,非的關係
# 查詢名字叫紅樓夢或者價格大於100的書
ret=Book.objects.filter(Q(name='紅樓夢')|Q(price__gt=100))
print(ret)
# 查詢名字叫紅樓夢和價格大於100的書
ret = Book.objects.filter(Q(name='紅樓夢') & Q(price__gt=100))
print(ret)
# # 等同於
ret2=Book.objects.filter(name='紅樓夢',price__gt=100)
print(ret2)
# 也能夠Q套Q
# 查詢名字叫紅樓夢和價格大於100 或者 nid大於2
ret=Book.objects.filter((Q(name='紅樓夢') & Q(price__gt=100))|Q(nid__gt=2))
print(ret)
# ----非
ret=Book.objects.filter(~Q(name='紅樓夢'))
print(ret)
# Q和鍵值對聯合使用,可是鍵值對必須放在Q的後面(描述的是一個且的關係)
# 查詢名字不是紅樓夢,而且價格大於100的書
ret=Book.objects.filter(~Q(name='紅樓夢'),price__gt=100)
print(ret)
# 查詢每個出版社出版的書籍個數ret=Book.objects.values('publish_id').annotate(Count('nid'))print(ret)