12.329 orm單表查詢
import
os
if
__name__
==
'
__main__
'
:
#
指定當前py腳本需要加載的Django項目配置信息
os.environ.setdefault(
"
DJANGO_SETTINGS_MODULE
"
,
"
orm_demo.settings
"
)
import
django
django.setup()
#
啟動Django項目
from
app01
import
models
#
返回QuerySet對象的方法:
ret =
models.Book.objects.all()
print
(ret)
#
QuerySet類型:書籍對象的列表
?
ret
= models.Book.objects.filter(title=
"
圍城
"
)
#
QuerySet類型 --> 書籍對象的列表
#
id值大于1
ret = models.Book.objects.filter(id__gt=1
)
#
id值小于3
ret = models.Book.objects.filter(id__lt=3
)
#
出版日期是2017年的書
ret = models.Book.objects.filter(publisher_date__year=2017
)
#
出版日期大于2017年
ret = models.Book.objects.filter(publisher_date__year__gt=2017
)
#
書名中包含'曌'的書
ret = models.Book.objects.filter(title__contains=
"
曌
"
)
#
書名中包含'曌'的書并且出版年份是2018年
ret = models.Book.objects.filter(title__contains=
"
曌
"
, publisher_date__year=2018
)
?
#
get方法如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
#
符合篩選條件的對象只有一個,則返回具體的類對象實例:書籍對象,而不是列表
ret = models.Book.objects.get(id=10
)
print
(ret)
#
報錯
#
使用filter檢索的時候沒有滿足條件的數據就返回一個空 QuerySet
ret = models.Book.objects.filter(id=10
)
print
(ret)
#
[]
?
#
將滿足條件的去掉,留下不滿足條件的
ret = models.Book.objects.exclude(id__in=[1,3,4
])
print
(ret)
#
按字段排序
ret = models.Book.objects.all().order_by(
"
price
"
)
#
QuerySet類型:根據price字段對所有數據排序
ret = models.Book.objects.all().order_by(
"
-price
"
)
#
反轉
ret = models.Book.objects.all().order_by(
"
price
"
).reverse()
#
按照出版時間排序后反轉再去字段值 # QuerySet類型:字段及字段值的字典的列表
ret = models.Book.objects.all().order_by(
"
publisher_date
"
).reverse().values(
"
title
"
)
#
特殊的QuerySet:
#
values() 取字段的值,以字典返回
ret = models.Book.objects.filter(publisher_date__year=2018).values(
"
title
"
,
"
publisher_date
"
)
print
(ret)
#
QuerySet類型:字段及字段值的字典的列表
#
values_list() 取字段的值,以元組返回
ret = models.Book.objects.filter(publisher_date__year=2018).values_list(
"
title
"
,
"
publisher_date
"
)
#
QuerySet類型:字段值的元祖的列表
#
連表查詢
ret = models.Book.objects.all().values(
"
publisher__name
"
).distinct()
print
(ret)
#
QuerySet類型:字段及字段值的字典的列表,并去重
?
#
返回數字的方法
#
count 計數
ret = models.Book.objects.all().count()
#
數字:結果集中數據的個數
#
返回具體對象
#
first()和last()
ret = models.Book.objects.all().first()
#
結果集中的第一個對象
#
get()
ret = models.Book.objects.get(id=1)
#
返回匹配到的對象,有且僅有一個
#
返回布爾值的方法
#
判斷結果集中是否有數據
ret = models.Book.objects.all().exists()
#
布爾值:結果集中是否有數據
12.3210 orm多表查詢(方式二)
ForeignKey操作: 書籍表(Book表)外鍵關聯出版社表(Publisher表)
正向查找:
1
.基于對象(子查詢)
book_obj
= models.Book.objects.first()
#
第一本書對象
print
(book_obj.publisher)
#
得到這本書關聯的出版社對象
print
(book_obj.publisher.name)
#
得到出版社對象的名稱
2
.基于雙下劃線字段方法(聯表查詢)
print
(models.Book.objects.values_list(
"
publisher__name
"
))
反向查找:
1
.基于對象(子查詢)
publisher_obj
= models.Publisher.objects.first()
#
找到第一個出版社對象
books = publisher_obj.book_set.all()
#
找到第一個出版社出版的所有書籍對象
titles = books.values_list(
"
title
"
)
#
找到第一個出版社出版的所有書籍的書名
#
如果設置了 related_name="books"
#
publisher= models.ForeignKey(to="Publisher", related_name="books")
publisher_obj =
models.Publisher.objects.first()
ret
=
publisher_obj.books.all()
print
(ret)
#
,
]>
?
2
.基于雙下劃線的字段方法(聯表查詢)
ret
= models.Publisher.objects.filter(id=1).values_list(
"
book__title
"
)
print
(ret)
#
titles = models.Publisher.objects.values_list(
"
book__title
"
)
print
(titles)
#
?
#
如果related_query_name="books"或者 related_name="books"(如果兩個同時出現,則以related_query_name為準)
titles = models.Publisher.objects.filter(id=1).values_list(
"
books__title
"
)
#
titles = models.Publisher.objects.filter(id=1).values(
"
books__title
"
)
#
ManyToManyField: (使用方式二:通過ManyToManyField自動創建第三張表)
models:
class
Book(models.Model):
title
= models.CharField(max_length=32
)
publish_date
= models.DateField(auto_now_add=
True)
price
= models.DecimalField(max_digits=5, decimal_places=2
)
memo
= models.TextField(null=
True)
#
創建外鍵,關聯publish
publisher = models.ForeignKey(to=
"
Publisher
"
, )
#
創建多對多關聯author
author = models.ManyToManyField(to=
"
Author
"
)
?
class
Author(models.Model):
name
= models.CharField(max_length=32
)
age
=
models.IntegerField()
phone
= models.CharField(max_length=11
)
detail
= models.OneToOneField(to=
"
AuthorDetail
"
)
class RelatedManager:"關聯管理器"是在 一對多 或者 多對多 的關聯上下文中使用的管理器。
它存在于下面兩種情況: 外鍵關系的反向查詢 、 多對多關聯關系 ,簡單來說就是當 "."后面的對象 可能存在多個的時候就可以使用以下的方法
create(): 創建一個新的對象,保存對象,并將它添加到關聯對象集之中,返回新創建的對象。
#
models.Book.objects.first().author得到是一個class RelatedManager對象,使用.create操作author表和第三張表
1
.正向創建author表數據
ret
= models.Book.objects.first().author.create(name=
"
張三
"
,age=16,phone=
"
18012xxxx
"
,detail_id=4
)
#
做了兩件事情:1. 創建了一個新的作者,2. 將新創建的作者和第一本書做關聯
ret = models.Book.objects.first().author.all().values(
"
id
"
)
print
(ret)
#
2
.反向創建book表數據
import
datetime
models.Author.objects.first().book_set.create(title
=
"
番茄物語
"
, publish_date=datetime.date.today())
add(): 把指定的model對象或對象id添加到關聯對象集中
#
添加對象
author_objs = models.Author.objects.filter(id__lt=3
)
models.Book.objects.first().author.add(
*
author_objs)
#
添加id
models.Book.objects.first().author.add(*[1, 2
])
models.Book.objects.first().author.add(
1
)
#
第一本書關聯的作者id
ret = models.Book.objects.first().author.all().values(
"
id
"
)
print
(ret)
#
set(): 更新model對象的關聯對象。
ret=models.Book.objects.first().author.set([2, 3])
#
設置第三張表的關聯關系,給第一個book對象加上id=2和3
ret =
models.Book.objects.first().author.all()
print
(ret)
#
,
,
]>
ret = models.Book.objects.first().author.all().values(
"
id
"
)
print
(ret)
#
remove(): 從關聯對象集中移除執行的model對象
models.Book.objects.first().author.remove(3)
#
找到第一個圖書對象所對應的所有作者,到第三張表中刪除它與id=3的作者的關聯關系#
ret = models.Book.objects.first().author.all().values(
"
id
"
)
print
(ret)
#
clear(): 從關聯對象集中移除一切對象。
#
models.Book.objects.first().author.clear()
ret
= models.Book.objects.first().author.all().values(
"
id
"
)
print
(ret)
#
注意:對于ForeignKey對象,clear()和remove()方法僅在null=True時存在
all():
ret = models.Book.objects.first().author.all()
#
得到第一本書對象對應的作者對象集
print
(ret)
#
12.3211 聚合查詢
aggregate()是QuerySet 的一個終止子句,它返回一個包含一些鍵值對的字典。
鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。
from
django.db.models
import
Avg, Sum, Max, Min, Count
models.Book.objects.all().aggregate(Avg(
"
price
"
))
#
{'price__avg': 13.233333}
ret = models.Book.objects.aggregate(Sum(
"
price
"
))
#
{'price__sum': Decimal('13.10')
ret = models.Book.objects.aggregate(total_price=Sum(
"
price
"
))
#
{'total_price': Decimal('13.10')}
ret = models.Book.objects.aggregate(avg_price=Avg(
"
price
"
), max_price=Max(
"
price
"
), min_price=Min(
"
price
"
))
#
{'avg_price': 4.366667, 'max_price': Decimal('12.00'), 'min_price': Decimal('0.10')}
12.3212 分組查詢
單表查詢分組:按照部門分組求平均工資
select
dept,
AVG
(salary)
from
employee
group
by
dept;
orm查詢:
from
django.db.models
import
Avg
models.Employee.objects.values(
"
dept
"
).annotate(avg=Avg(
"
salary
"
)
#
models.Employee.objects.values(
"
dept
"
).annotate(avg=Avg(
"
salary
"
).values(
'
dept
'
,
"
avg
"
)
#
連表查詢的分組:按照部門分組求平均工資
select
dept.name,
AVG
(salary)
from
employee
inner
join
dept
on
(employee.dept_id
=
dept.id)
group
by
dept_id;
ORM查詢:
from
django.db.models
import
Avg
models.Dept.objects.annotate(avg
=Avg(
"
employee__salary
"
)).values(
"
name
"
,
"
avg
"
)
?
models.Employee.objects.values(
"
dept__name
"
).annotate(avg=Avg(
"
salary
"
))
#
?
models.Employee.objects.values(
"
dept__name
"
).annotate(avg=Avg(
"
salary
"
)).values(
'
dept
'
,
"
avg
"
)
#
?
models.Employee.objects.values(
"
dept__name
"
)
#
作者、圖書、出版社表關系:
from
django.db
import
models
#
出版社
class
Publisher(models.Model):
name
= models.CharField(max_length=32
)
city
= models.CharField(max_length=32
)
#
書
class
Book(models.Model):
title
= models.CharField(max_length=32
)
publish_date
= models.DateField(auto_now_add=
True)
price
= models.DecimalField(max_digits=5, decimal_places=2
)
#
創建外鍵,關聯publish
publisher = models.ForeignKey(to=
"
Publisher
"
)
#
創建多對多關聯author
author = models.ManyToManyField(to=
"
Author
"
)
#
作者
class
Author(models.Model):
name
= models.CharField(max_length=32)
示例:
1
.統計每一本書的作者個數
(
1):ret = models.Book.objects.annotate(autor_num=Count(
"
author
"
)).values(
"
title
"
,
"
autor_num
"
)
#
?
(
2):book_list = models.Book.objects.all().annotate(author_num=Count(
"
author
"
))
print
(book_list)
#
,
,
]>
for
obj
in
book_list:
print
(obj.author_num)
#
0 1 1
2
.統計出每個出版社出版的最便宜的書的價格
(
1):ret = models.Publisher.objects.annotate(min_price=Min(
"
book__price
"
)).values(
"
name
"
,
"
min_price
"
)
#
{
'
name
'
:
'
北大青鳥出版社
'
,
'
min_price
'
: None}]>
(
2):ret=models.Book.objects.values(
"
publisher__name
"
).annotate(min_price=Min(
"
price
"
))
#
?
(
3):publisher_list = models.Publisher.objects.annotate(min_price=Min(
"
book__price
"
))
print
(publisher_list)
#
,
,
]>
for
obj
in
publisher_list:
print
(obj.min_price)
#
0.10 12.00 None
3
.統計不止一個作者的圖書
models.Book.objects.annotate(author_num
=Count(
"
author
"
)).filter(author_num__gt=1)
#
4
.根據一本圖書作者數量的多少對查詢集 QuerySet進行排序
models.Book.objects.annotate(author_num
=Count(
"
author
"
)).order_by(
"
author_num
"
)
#
,
,
]>
5
.查詢各個作者出的書的總價格
models.Author.objects.annotate(sum_price
=Sum(
"
book__price
"
)).values(
"
name
"
,
"
sum_price
"
)
#
#
{'name': '大烏龜', 'sum_price': None}, {'name': '張san', 'sum_price': None}]>
12.3213 F查詢
F() 的實例可以在查詢中引用字段,來比較同一個 model 實例中兩個不同字段的值。
商品表結構:
from
django.db
import
models
?
class
Product(models.Model):
name
= models.CharField(max_length=32
)
price
= models.DecimalField(max_digits=6, decimal_places=2
)
#
庫存數
keep =
models.IntegerField()
#
賣出數
sale =
models.IntegerField()
?
def
__str__
(self):
return
"
{}:{}:{}:{}
"
.format(self.name, self.price, self.keep, self.sale)
示例:
from
django.db.models
import
F
1
.查詢出賣出數大于庫存數的商品
models.Product.objects.filter(sale__gt
=F(
"
keep
"
))
#
,
]>
2
.Django支持F()對象之間以及F()對象和常數之間的加減乘除和取模的操作
models.Product.objects.filter(sale__gt
=F(
'
keep
'
)*2
)
#
]>
3
.修改操作也可以使用F函數:比如將每個產品的價格提高50元
models.Product.objects.all().update(price
=F(
"
price
"
)+50
)
4.把所有商品名后面加上
"
新款
"
from
django.db.models.functions
import
Concat
from
django.db.models
import
Value
models.Product.objects.all().update(name
=Concat(F(
"
name
"
), Value(
"
新款
"
)))
12.3214 Q查詢
filter() 等方法中的關鍵字參數查詢都是一起進行“AND” 的。 如果需要執行更復雜的查詢(例如OR語句),可以使用Q對象
#
賣出數大于100 并且 價格大于100塊的
models.Product.objects.filter(sale__gt=100, price__gt=100
)
#
,
]>
示例:
from
django.db.models
import
Q
1
.查詢賣出數大于100或者價格小于100的
models.Product.objects.filter(Q(sale__gt
=100)|Q(price__lt=100))
#
|:或
#
,
]>
2
.查詢庫存數是100并且賣出數不是0的產品
models.Product.objects.filter(Q(keep
=100)&~Q(sale=0))
#
&:與,~:非
models.Product.objects.filter(Q(kucun=100),~Q(maichu=
0))
#
]>
models.Product.objects.filter(Q(kucun=100)&~Q(maichu=0)).values(
'
name
'
)
#
models.Product.objects.filter(Q(kucun=100)&~Q(maichu=0)).values_list(
'
name
'
)
#
查詢函數可以混合使用Q 對象和關鍵字參數。所有提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND”在一起。但是,如果出現Q 對象,它必須位于所有關鍵字參數的前面
#
查詢產品名包含新款, 并且庫存數大于60或者價格小于100的產品
models.Product.objects.filter(Q(keep__gt=60)|Q(price__lt=100), name__contains=
"
新款
"
)
#
]>
12.3215 事務
開啟一個事務可以包含一些sql語句,這些sql語句要么同時成功,要么都不成功,稱之為事務的原子性 作用:事務用于將某些操作的多個SQL作為原子性操作,一旦有某一個出現錯誤,即可回滾到原來的狀態,從而保證數據庫數據完整性。
import
os
if
__name__
==
'
__main__
'
:
os.environ.setdefault(
"
DJANGO_SETTINGS_MODULE
"
,
"
BMS.settings
"
)
import
django
django.setup()
import
datetime
from
app01
import
models
try
:
from
django.db
import
transaction
with transaction.atomic():
#
開啟事務
new_publisher = models.Publisher.objects.create(name=
"
火星出版社
"
)
models.Book.objects.create(title
=
"
橘子物語
"
, publish_date=datetime.date.today(), publisher_id=10
)
#
指定一個不存在的出版社id,上一行創建一條出版社數據被回滾,數據庫并未創建新數據
except
Exception as e:
print
(str(e))
12.3216 Django ORM執行原生SQL
很多情況下我們不需要將查詢結果映射成模型,或者我們需要執行DELETE、 INSERT以及UPDATE操作,在這些情況下,我們可以直接訪問數據庫,完全避開模型層。我們可以直接從django提供的接口中獲取數據庫連接,然后像使用pymysql模塊一樣操作數據庫
from
django.db
import
connection, connections
cursor
= connection.cursor()
#
cursor = connections['default'].cursor()
cursor.execute(
"""
SELECT * from auth_user where id = %s
"""
, [1
])
ret
= cursor.fetchone()
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

