??????個人簡介:以山河作禮。
??????:Python領域新星創(chuàng)作者,CSDN實力新星認證,阿里云社區(qū)專家博主,CSDN內容合伙人
????:Web全棧開發(fā)專欄:《Web全棧開發(fā)》免費專欄,歡迎閱讀!
????:文章末尾掃描二維碼可以加入粉絲交流群,不定期免費送書。
Django查詢數(shù)據(jù)庫操作
基礎操作
添加數(shù)據(jù)
存儲數(shù)據(jù)需要通過save方法進行存儲
# 添加數(shù)據(jù)1
Book(title='張三',price=222,author=Author.objects.get(id=1)).save()
# 添加數(shù)據(jù)2
# Book.objects.create(title='張三',price=222,author=Author.objects.get(id=1)).save()
# 打印數(shù)據(jù)
data = Book.objects.all() # 獲取全部數(shù)據(jù)
for book in data:
print(book.title, book.price, book.author.name)
修改數(shù)據(jù)
# 修改數(shù)據(jù)
from datetime import date
book = Book.objects.get(title='張三')
# # book.publish_date = date(2022, 1, 1)
book.price = 555
book.save() # 更新數(shù)據(jù),保存到數(shù)據(jù)庫中
刪除數(shù)據(jù)
# 刪除數(shù)據(jù)
book = Book.objects.get(title='張三')
book.delete() # 刪除數(shù)據(jù)
查詢數(shù)據(jù)
查詢所有書籍:
books = Book.objects.all()
查詢 title 字段為 Python 的書籍(精確匹配):
books = Book.objects.filter(title='Python')
其中
filter()
方法對模型進行過濾。這個方法接受關鍵字參數(shù)作為查詢條件,可以進行鏈式操作。
假設我們有一個名為 Person
的模型,其中有一個屬性 age
表示人的年齡,我們可以使用如下代碼來查詢年齡大于等于 18 歲的人:
results = Person.objects.filter(age__gte=18)
在這個例子中,我們使用
filter()
方法對模型進行過濾,傳遞給它一個查詢條件age__gte=18
,其中gte
表示大于等于查詢操作符,18
是年齡篩選條件。這個查詢可以返回所有年齡大于等于 18 歲的人。
- 需要注意的是,如果要對查詢結果進行多次條件操作,可以使用鏈式操作。
例如,如果我們需要查詢所有年齡大于等于 18 歲且性別為男的人,可以使用以下代碼:
results = Person.objects.filter(age__gte=18, gender='male')
在這個例子中,我們在第一次查詢過濾后使用了第二次的查詢條件
gender='male'
,即查詢所有性別為男,年齡大于等于 18 歲的人。
- 需要注意的是,在 filter 查詢操作中,需要使用雙下劃線(
__
)進行多條件查詢,例如age__gte
表示查詢大于等于指定年齡,gender__icontains
表示查詢包含指定性別(不區(qū)分大小寫)的記錄等等。
查詢 rating 不等于 1 的書籍:
results = Book.objects.exclude(rating = 1)
其中的 exclude()
方法對模型進行過濾并排除某些不需要的數(shù)據(jù),即排除指定查詢條件的結果。這個方法與 filter()
方法一樣,接受關鍵字參數(shù)作為查詢條件,可以進行鏈式操作。
假設我們有一個名為 Person
的模型,其中有一個屬性 age
表示人的年齡,我們可以使用如下代碼來排除所有年齡小于 18 歲的人:
results = Person.objects.exclude(age__lt=18)
在這個例子中,我們使用
exclude()
方法對模型進行過濾,傳遞給它一個排除條件age__lt=18
,其中lt
表示小于查詢操作符,18
是年齡篩選條件。這個查詢可以排除所有年齡小于 18 歲的人。
需要注意的是,如果要對查詢結果進行多次排除條件操作,可以使用鏈式操作。例如,如果我們需要排除所有年齡小于 18 歲且沒有指定性別的人,可以使用以下代碼:
results = Person.objects.exclude(age__lt=18).exclude(gender=None)
在這個例子中,我們在第一次排除過濾后使用了第二次的排除條件
exclude(gender=None)
,即排除所有性別未知的年齡小于 18歲的人。
- 需要注意的是,在 exclude 查詢操作中,需要使用雙下劃線(
__
)進行多條件查詢,例如age__lt
表示查詢小于指定年齡,gender__icontains
表示查詢包含指定性別(不區(qū)分大小寫)的記錄等等。
exclude() 和 filter()方法區(qū)別
- exclude() 和 filter() 方法都是在 Django 中對模型進行查詢的常用方法,它們的區(qū)別在于查詢的方向不同。
- filter() 方法是對模型查詢符合條件的記錄,即從數(shù)據(jù)集中選取數(shù)據(jù)滿足查詢條件。而exclude()方法則是從模型中排除不符合查詢條件的記錄,即從數(shù)據(jù)集中去除數(shù)據(jù)不滿足查詢條件。
- 在應用時,filter() 方法通常用于基礎查詢場合,比如查詢某個模型中的所有記錄、查詢符合某個條件的記錄等。exclude()方法通常用于復雜的查詢場合,比如查詢一個模型中的記錄中滿足某些條件而排除滿足其他條件的記錄等。
例如,當我們要查詢年齡大于等于 18 歲的人時,我們可以使用 filter() 方法:
results = Person.objects.filter(age__gte=18)
當我們要查詢年齡不是 18 歲的人時,則需要使用 exclude() 方法:
results = Person.objects.exclude(age=18)
在這個例子中,我們使用 filter() 方法查詢年齡大于等于 18 歲的人,而使用 exclude() 方法排除年齡為 18 歲的人。
比較運算符
比較運算符用于篩選符合條件的數(shù)據(jù)
比較運算符 | 含義 | 使用方法 |
---|---|---|
= |
等于 | Person.objects.filter(age=18) |
!= |
不等于 | Person.objects.exclude(age=18) |
> |
大于 | Person.objects.filter(age__gt=18) |
>= |
大于等于 | Person.objects.filter(age__gte=18) |
< |
小于 | Person.objects.filter(age__lt=18) |
<= |
小于等于 | Person.objects.filter(age__lte=18) |
in |
在給定的范圍內 | Person.objects.filter(age__in=[18, 19, 20]) |
range |
在給定的范圍內 | Person.objects.filter(age__range=(18, 20)) |
contains |
包含指定值 | Person.objects.filter(name__contains='Jack') |
icontains |
包含指定值(不區(qū)分大小寫) | Person.objects.filter(name__icontains='Jack') |
startswith |
以指定值開頭 | Person.objects.filter(name__startswith='Jack') |
istartswith |
以指定值開頭(不區(qū)分大小寫) | Person.objects.filter(name__istartswith='Jack') |
endswith |
以指定值結尾 | Person.objects.filter(name__endswith='Smith') |
iendswith |
以指定值結尾(不區(qū)分大小寫) | Person.objects.filter(name__iendswith='Smith') |
邏輯符號
在 Django 中進行查詢時,通常需要通過邏輯符將查詢條件組合在一起。以下是 Django 查詢中需要用到的邏輯符,以及它們的含義和使用方式,以 Markdown 表格的形式列出:
邏輯符 | 含義 | 使用方法 |
---|---|---|
Q() |
邏輯或( OR ) | `Person.objects.filter(Q(age__lt=18) |
& |
邏輯與( AND ) | Person.objects.filter(age__lt=18, gender='male') |
\~Q() |
邏輯非( NOT ) | Person.objects.exclude(~Q(age__lt=18)) |
- 邏輯或( OR ):可以使用
Q()
對象聯(lián)合兩個或多個查詢條件,實現(xiàn)邏輯或的查詢,其中|
是邏輯或運算符。例如,查詢年齡小于 18 歲或性別為男的人可以使用:Person.objects.filter(Q(age__lt=18) | Q(gender='male'))
。 - 邏輯與( AND ):可以使用
&
運算符組合多個查詢條件,實現(xiàn)邏輯與的查詢。例如,查詢年齡小于 18 歲且性別為男的人可以使用:Person.objects.filter(age__lt=18, gender='male')
。 - 邏輯非( NOT ):可以使用
~Q()
對象表示查詢結果的逆,實現(xiàn)邏輯非的查詢,其中~
是邏輯非運算符。例如,查詢年齡不是小于 18 歲的人可以使用:Person.objects.exclude(~Q(age__lt=18))
。
需要注意的是,當多個邏輯運算符混合使用時,需要使用小括號對查詢條件進行分組,以保證查詢的順序正確,例如:
from django.db.models import Q
Person.objects.filter(Q(age__lt=18) | (Q(gender='male') & Q(city='北京')))
在這個例子中,使用小括號將
gender
和city
的查詢條件進行分組,確保查詢邏輯正確。
查詢 publish_date 在某個時間段以內的書籍:
import datetime
start_date = datetime.date(2021, 1, 1)
end_date = datetime.date(2021, 12, 31)
books = Book.objects.filter(publish_date__range=(start_date, end_date))
values(‘my_field’,‘list_datra’) values獲取數(shù)據(jù)查詢集的字段 ,返回字段類型
values_list(‘my_field’,'list_datra) 獲取數(shù)據(jù)查詢集的字段 ,返回列表類型
去重查詢
from myapp.models import MyModel
# 去重查詢,返回去重后的所有 MyModel 對象
distinct_objects = MyModel.objects.all().distinct()
# 去重查詢,返回去重后的某個字段的值的集合
distinct_values = MyModel.objects.values('my_field').distinct()
分組集合:
annotate()
方法進行分組集合查詢。
from django.db.models import Count
from myapp.models import MyModel
# 獲取按照 category 分組后的 count 值,返回分組后的 QuerySet 對象
count_by_category = MyModel.objects.values('category').annotate(count=Count('category'))
- 可以使用的聚合函數(shù)還包括 Sum、Avg、Min 和 Max 等等,你可以根據(jù)自己的需要使用不同的聚合函數(shù)來計算分組聚合后的結果。
需要注意的是, annotate()
方法和 distinct()
方法一樣,都是應用于 QuerySet 對象或相關的 Manager 方法中,并且會創(chuàng)建一個新的查詢集。我們還可以使用 filter()
方法和 exclude()
方法對分組對象進行過濾和排除。
例如,你可以按照如下方式獲取 category 字段中計數(shù)大于 10 的對象:
count_gt_10 = MyModel.objects.values('category').annotate(count=Count('category')).filter(count__gt=10)
在這個示例中,我們在
annotate()
方法之后使用filter()
方法對分組后的對象進行了過濾,只保留了計數(shù)大于 10的對象。
排序查詢:
order_by()
方法進行排序查詢。
from myapp.models import MyModel
# 對 name 字段進行升序排序
ascending_objects = MyModel.objects.all().order_by('name')
對 name 字段進行升序排序,然后對 age 字段進行降序排序:
# 對 name 字段進行升序排序,對 ages 字段進行降序排序
ascending_then_descending_objects = MyModel.objects.all().order_by('name', '-age')
在這個示例中,我們在
order_by()
方法的第一個參數(shù)中指定了name
字段,并在第二個參數(shù)中指定了-age
,表示要對age
字段進行降序排序。
- 需要注意的是,
order_by()
方法只能應用于可以比較相等的字段,因此不能用于像二進制字段或大文本字段這樣的大對象字段上。此外,排序查詢也可以與其他查詢方法filter()
、exclude()
和annotate()
等組合使用。
分頁操作
Paginator
類實現(xiàn)分頁查詢。Paginator 是一個支持分頁操作的類,可以將一系列對象按照固定的數(shù)量分隔成多個頁面。
使用 Paginator
類的步驟如下:
- 首先,從 Django 的
core.paginator
模塊導入Paginator
類:
from django.core.paginator import Paginator
- 接下來,獲取一個 QuerySet 或者一個列表數(shù)據(jù),通常是從數(shù)據(jù)庫中查詢到的:
data_list = MyModel.objects.all()
- 使用 Paginator 類對查詢到的數(shù)據(jù)進行分頁設置。例如,將查詢到的數(shù)據(jù)劃分成每頁5個:
paginator = Paginator(data_list, 5)
- 最后,從需要顯示數(shù)據(jù)的頁面中獲取頁碼并使用 Paginator 對象返回對應的 QuerySet,從而實現(xiàn)分頁查詢:
page_number = request.GET.get('page') # 獲取當前請求的頁碼
data_page = paginator.get_page(page_number) # 獲取對應頁碼的數(shù)據(jù)
在這個例子中,我們從請求中獲取到需要顯示的頁碼
page_number
,然后使用get_page()
方法返回對應頁碼的數(shù)據(jù)。get_page()
方法還可以自動處理非數(shù)字或者小于 1 的頁碼,會返回合法的頁碼且保持在范圍內。如果請求的頁碼超出范圍,get_page()
會返回第一頁或最后一頁的數(shù)據(jù)。
需要注意的是, Paginator
類可能會導致大量的查詢操作,因此我們在使用它時應該考慮如何優(yōu)化查詢。
模糊查詢
使用 QuerySet 的 filter()
方法和 icontains
查詢操作符來進行模糊查詢。icontains
可以用于查找包含指定字符串的記錄,不區(qū)分大小寫。
例如,如果我們有一個名為 Person
的模型,其中有一個字段 name
表示人名,我們可以使用如下代碼來模糊查詢名字中包含 “john” 的人:
results = Person.objects.filter(name__icontains='john')
-
__icontains
表示不區(qū)分大小寫的包含查詢操作符,'john'
是要查找的字符串內容。 - 需要注意的是,進行模糊查詢操作時,如果數(shù)據(jù)集過大,可能會影響性能。在實際開發(fā)中,應該根據(jù)實際情況使用合理的查詢條件和數(shù)據(jù)庫索引來優(yōu)化查詢效率。
- 在 Django 中,可以使用正則表達式進行模糊查詢,具體使用方法是使用
regex
查詢操作符和re
模塊中的正則表達式語法進行匹配。
假設我們有一個名為 Person
的模型,其中有一個字段 name
表示人名,我們可以使用如下代碼來使用正則表達式查詢名字中包含字母 “j” 或 “o” 的人:
import re
pattern = r'[jo]'
results = Person.objects.filter(name__regex=pattern)
需要注意的是,使用正則表達式進行模糊查詢需要注意以下幾點:
- 正則表達式不是 SQL 的一部分,查詢速度可能會比簡單的 SQL 查詢慢,因此盡量減少正則表達式的使用,只在必要時使用。
- 正則表達式的語法較為復雜,需要了解正則表達式的語法和用法才能使用。
- 正則表達式匹配的查詢條件應該根據(jù)實際情況進行優(yōu)化,盡量減少不必要的模式匹配過程,以提高查詢效率。
多表查詢
在 Django 中,可以使用相關對象和 filter()
方法進行多表查詢。相關對象是指模型類中通過 ForeignKey、OneToOneField 或 ManyToManyField 字段所定義的關聯(lián)關系。
假設我們有兩個模型類 Author
和 Book
,其中 Book
模型類通過 ForeignKey
字段關聯(lián)到了 Author
模型類,表示一本書只能屬于一位作者?,F(xiàn)在我們想要查詢所有書名以 “Django” 開頭的作者及其所寫的所有書籍,代碼示例如下:
from myapp.models import Author, Book
authors = Author.objects.filter(book__title__startswith='Django')
在這里我們首先導入
Author
和Book
模型類,然后使用filter()
方法對Author
模型類進行過濾,篩選條件為book__title__startswith='Django'
,其中book
是Author
模型中的ForeignKey
關聯(lián)字段,title
是Book
模型類中的屬性名,表示書籍的名稱,startswith
是字符串查詢操作符,表示篩選書名以 “Django” 開頭的記錄。
通過上述查詢,我們可以得到所有書籍名以 “Django” 開頭的作者,接著通過 Author
模型類中的 book_set
屬性獲取每個作者所寫的所有書籍,示例代碼如下:
for author in authors:
books = author.book_set.all()
for book in books:
print(author.name, book.title)
在這里,我們使用
for
循環(huán)遍歷每個查詢到的作者實例對象,然后使用author.book_set.all()
獲取該作者所寫的所有書籍。由于Book
模型類中ForeignKey
關聯(lián)字段默認生成的related_name
屬性為book_set
,因此我們可以使用author.book_set
獲取該作者所寫的所有書籍。接著再使用for
循環(huán)遍歷每本書,輸出書籍名稱和作者名稱。
- 需要注意的是,如果是多個模型之間的復雜查詢,最好使用 Django 內置的 ORM 或第三方的 QueryBuilder來進行多表查詢,而不是直接編寫原生 SQL 語句,這樣可以提高開發(fā)效率并避免 SQL 注入安全問題。
執(zhí)行原生 SQL
Django 提供了游標 cursor 對數(shù)據(jù)庫進行增刪改操作,在 Django 中執(zhí)行非查詢語句必須使用游標進行操作。游標 cursor 定義在 django.db.connection 包中,使用前用下面的方式進行導入:
from django.db import connection
用創(chuàng)建 cursor 類的構造函數(shù)創(chuàng)建 cursor 對象,再使用 cursor 對象執(zhí)行 SQL 語句。為確保能夠在出現(xiàn)異常時釋放 cursor 游標,通常使用 with 語句進行創(chuàng)建操,如下所示:文章來源:http://www.zghlxwxcb.cn/news/detail-539843.html
from django.db import connection
with connection.cursor() as cur:
cur.execute('執(zhí)行SQL語句')
使用示例如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-539843.html
from django.db import connection
with connection.cursor() as cur:
#調用游標對象的execute方法,更新author的名字
cur.execute('update index_author set name="Jack" where id=3;')
with connection.cursor() as cur:
# 刪除id為3的一條author記錄
cur.execute('delete from index_author where id=3;')
with connections.cursor() as cursor:
cursor.execute('SELECT * FROM my_table WHERE some_field > %s', [some_value])
result = cursor.fetchall()
- 開發(fā)建議使用 Django ORM 中的高級查詢,例如
filter
、exclude
、annotate
、values
等方法,這些方法可以構建復雜的查詢條件,并且支持鏈式調用,便于代碼維護和可讀性。 - ORM 查詢的好處是它是語言級別的,且與數(shù)據(jù)庫類型無關,使你的代碼更加可移植。ORM 還提供了自動構造 SQL查詢語句的功能,省去了手動構造 SQL 語句的繁瑣和容易出錯的過程。
- 當然,在某些特定情況下,ORM 查詢不能滿足需求,例如需要執(zhí)行復雜的聚合函數(shù),或者需要執(zhí)行跨數(shù)據(jù)庫的 SQL 查詢。這時候可以考慮使用Django 的
connections
模塊執(zhí)行原生 SQL 查詢,但需要注意避免 SQL 注入攻擊。
到了這里,關于Django基礎入門⑩:Django查詢數(shù)據(jù)庫操作詳講的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!