1. 程式人生 > >django的資料庫操作-16

django的資料庫操作-16

目錄

Django的manage工具提供了shell命令,已經幫助我們配置好當前工程的執行環境(如連線好資料庫等),我們會在自帶終端中執行測試python語句。

manage.py 所在目錄執行命令

python manage.py shell

這打開了一個互動式命令列。

匯入模型類

from book.models import Book
from book.models import Role

匯入date包處理時間

from datetime import date

增加資料有兩種方式

1.save

建立模型類物件,再使用 save 儲存到資料庫中

新增書籍 “西遊記”

book = Book(
    b_title="西遊記", 
    b_pub_date=date(1988,1,1), 
    b_read=20, 
    b_comment=10, 
    is_delete=False)
    
>>> book.save()

2.create

直接儲存到資料庫中

“西遊記”書籍新增角色 “孫悟空”

Role.objects.create(
r_name="孫悟空", 
r_gender="1", 
r_describe="猴哥", 
r_book_id=book.id)

1.基本查詢

get 查詢單一結果,如果不存在會丟擲模型類.DoesNotExist異常,返回一個模型類物件。

all 查詢多個結果,返回一個查詢集。

count 查詢結果數量。

get

get 查詢單一結果,如果不存在會丟擲模型類.DoesNotExist異常。

查詢編號為5的書籍

>>> Book.objects.get(pk=5)
<Book: Book object>

objects 是模型管理器,會在後邊有具體的講解。

pk代表primary key的縮寫,也就是任何model中都有的主鍵,當id也是主鍵的時候,我們可以認為pk和id是完全一樣的。但是當model的主鍵不是id的時候,兩者就有了區別。

輸出出來的 <Book: Book object> 無法看出是不是我們寫進去的資料,為了讓顯示更人性化,我們給資料庫模型新增一個 _str__ 方法。

class Book(models.Model):
    ...
    def __str__(self):
        return self.b_title

class Role(models.Model):
    ...
    def __str__(self):
        return self.r_name

重啟shell,重新匯入模型類

>>> Book.objects.get(id=5)
<Book: 西遊記>

all

all 查詢多個結果。

查詢所有書

>>> Book.objects.all()
<QuerySet [<Book: 射鵰英雄傳>, <Book: 天龍八部>, <Book: 笑傲江湖>, <Book: 雪山飛狐>, <Book: 西遊記>]>

count

count 查詢結果數量。

獲得書籍數量

>>> Book.objects.count()
5

2.過濾查詢

過濾查詢實現sql語句中的 where 功能,包括:

filter 過濾出多個結果,返回一個查詢集

exclude 排除掉符合條件剩下的結果,返回一個查詢集

get 過濾單一結果

過濾查詢語法:

模型類名.objects.查詢方式(過濾條件)

過濾條件語法:

欄位名稱__條件運算子=值

條件運算子:

exact:相等。

contains:包含。

startswith:指定值開頭

endswith:指定值結尾

isnull:是否為null。

in:是否包含在範圍內。

gt: 大於 (greater then)

gte: 大於等於 (greater then equal)

lt: 小於 (less then)

lte: 小於等於 (less then equal)

year、month、day、week_day、hour、minute、second:對日期時間型別的屬性進行運算。

相等

exact:表示相等

查詢書名等於“西遊記”的書

>>> Book.objects.filter(b_title__exact="西遊記")
<QuerySet [<Book: 西遊記>]>

包含(模糊查詢)

contains:包含

書名包含“八”字的書

>>> Book.objects.filter(b_title__contains="八")
<QuerySet [<Book: 天龍八部>]>

開頭

書名“笑”開頭的數

>>> Book.objects.filter(b_title__startswith="笑")
<QuerySet [<Book: 笑傲江湖>]>

結尾

>>> Book.objects.filter(b_title__endswith="狐")
<QuerySet [<Book: 雪山飛狐>]>

isnull:是否為null

書名不為空

>>> Book.objects.filter(b_title__isnull=False)
<QuerySet [<Book: 射鵰英雄傳>, <Book: 天龍八部>, <Book: 笑傲江湖>, <Book: 雪山飛狐>, <Book: 西遊記>]>

包含(範圍)

in:是否包含在範圍內

編號 1,2,3的書

>>> Book.objects.filter(pk__in=[1, 2, 3])
<QuerySet [<Book: 射鵰英雄傳>, <Book: 天龍八部>, <Book: 笑傲江湖>]>

大於小於

gt: 大於 (greater then)
gte: 大於等於 (greater then equal)
lt: 小於 (less then)
lte: 小於等於 (less then equal)

編號大於3的書

>>> Book.objects.filter(pk__gt=3)
<QuerySet [<Book: 雪山飛狐>, <Book: 西遊記>]>

時間

year、month、day、week_day、hour、minute、second:對日期時間型別的屬性進行運算。

1995年的書

>>> Book.objects.filter(b_pub_date__year="1995")
<QuerySet [<Book: 笑傲江湖>]>

3. F物件

F()是代表模型欄位的值,可以用來修改欄位或者比較欄位。

匯入F物件

from django.db.models import F

F物件使用

F(欄位名)

閱讀量大於評論量

>>> Book.objects.filter(b_read__gt=F('b_comment'))
<QuerySet [<Book: 雪山飛狐>, <Book: 西遊記>]>

閱讀量大於評論量兩倍

>>> Book.objects.filter(b_read__gt=F('b_comment')*2)
<QuerySet [<Book: 雪山飛狐>]>

4. Q物件

隨著程式的複雜,查詢條件也會越來越複雜,類似前邊的查詢語句也會變得越來越長。

例如查詢閱讀量大於20且評論數大於30的書,需要這樣

>>> book = Book.objects.filter(b_read__gt=20)
>>> book.filter(b_comment__gt=30)
<QuerySet [<Book: 天龍八部>]>

或者這樣

>>> Book.objects.filter(b_read__gt=20).filter(b_comment__gt=30)
<QuerySet [<Book: 天龍八部>]>

但是這樣的語句是相當繁雜且不利於閱讀的。

Q()物件就是為了將這些條件組合起來。

Q物件可以使用 & | ~ 連線,& 表示邏輯與, | 表示邏輯或,~ 表示非。
類似sql語句中where部分的 and or not 關鍵字。

匯入Q物件

from django.db.models import Q

使用Q物件實現查詢閱讀量大於20且評論數大於30的書

>>> Book.objects.filter(Q(b_read__gt=20)&Q(b_comment__gt=30))
<QuerySet [<Book: 天龍八部>]>

5. 聚合函式

使用aggregate()過濾器呼叫聚合函式。聚合函式包括:Avg 平均,Count 數量,Max 最大,Min 最小,Sum 求和。

需要從 django.db.models 中匯入,例如

from django.db.models import Sum

查詢最多閱讀數

>>> Book.objects.aggregate(Max('b_read'))
{'b_read__max': 58}

聚合函式查詢結果是一個字典型別

{'欄位名__聚合類小寫': 查詢結果}

6. 排序

使用 order_by 對查詢結果排序,返回一個查詢集。

按閱讀量排序

>>> Book.objects.all().order_by('b_read')  # 升序排序
<QuerySet [<Book: 射鵰英雄傳>, <Book: 笑傲江湖>, <Book: 西遊記>, <Book: 天龍八部>, <Book: 雪山飛狐>]>
>>> Book.objects.all().order_by('-b_read')  # 降序排序
<QuerySet [<Book: 雪山飛狐>, <Book: 天龍八部>, <Book: 笑傲江湖>, <Book: 西遊記>, <Book: 射鵰英雄傳>]>

7. 關聯查詢

一查多

語法

一方查詢物件.多方模型類名小寫__set

查詢“天龍八部”所有的角色

>>> book = Book.objects.get(b_title__exact="天龍八部")
>>> book.role_set.all()
<QuerySet [<Role: 喬峰>, <Role: 段譽>, <Role: 虛竹>, <Role: 王語嫣>]>

多查一

語法

多方查詢物件.多方有對應關係的欄位名

查詢“段譽”所在書名

>>> role = Role.objects.get(r_name__exact="段譽")
>>> role.r_book
<Book: 天龍八部>

8. 關聯+過濾查詢

根據多方條件查一方

語法格式

多方模型類名小寫__多方欄位名__條件運算子=值

查詢編號為1角色所在書籍

>>> Book.objects.filter(role__id__exact=1)
<QuerySet [<Book: 射鵰英雄傳>]>

查詢角色名字帶“黃”字的書籍

>>> Book.objects.filter(role__r_name__contains="黃")
<QuerySet [<Book: 射鵰英雄傳>, <Book: 射鵰英雄傳>]>

當查詢條件為等於的時候可以省略條件運算子

查詢編號為1角色所在書籍可以這樣寫

>>> Book.objects.get(role__id=1)
<Book: 射鵰英雄傳>

根據一方條件查多方

語法格式

多方有對應關係的欄位名__一方欄位名__查詢條件=值

查詢“雪山飛狐所有角色”

>>> Role.objects.filter(r_book__b_title__exact="雪山飛狐")
<QuerySet [<Role: 胡斐>, <Role: 苗若蘭>, <Role: 程靈素>, <Role: 袁紫衣>]>

查詢閱讀量大於30的書籍角色

>>> Role.objects.filter(r_book__b_read__gt=30)
<QuerySet [<Role: 喬峰>, <Role: 段譽>, <Role: 虛竹>, <Role: 王語嫣>, <Role: 胡斐>, <Role: 苗若蘭>, <Role: 程靈素>, <Role: 袁紫衣>]>

當查詢條件是等於的時候可以省略條件運算子

查詢“雪山飛狐所有角色”可以這樣寫

>>> Role.objects.filter(r_book__b_title="雪山飛狐")
<QuerySet [<Role: 胡斐>, <Role: 苗若蘭>, <Role: 程靈素>, <Role: 袁紫衣>]>

刪除資料使用查詢結果物件的 delete 方法

語法格式

查詢結果物件.delete()

刪除閱讀量小於20的書

>>> Book.objects.filter(b_read__lt=20).delete()
(6, {'book.Role': 5, 'book.Book': 1})

一般刪除資料只使用邏輯刪除,即修改 is_delete 欄位為 True

修改資料有兩種方式

1. save

獲得 單個模型類 物件,修改資料後使用save儲存

>>> role = Role.objects.get(id__exact=18)
>>> role.r_name = "齊天大聖"
>>> role.save()

2. update

獲得 查詢集 物件,使用 update 方法修改資料,修改後會返回被影響資料條數

修改 id 大於15的角色名字為 “不知名人士”

>>> Role.objects.filter(id__gt=15).update(r_name="不知名人士")
4