Django筆記三之使用model對資料庫進行增刪改查

2023-03-20 06:00:31

本篇筆記目錄索引如下:

  1. model 準備

1、model 準備

在上一篇筆記中,我們新建了一個 application,增加了幾個model 同步到了資料庫,這次我們新建一個名為 blog 的application,同步資料結構。
大概分為以下幾步:

  • python3 manage.py startapp blog
  • 將 'blog.apps.BlogConfig’, 寫入 settings.py INSTALLED_APPS
  • 更新 blog/models.py
  • python3 manage.py makemigrations blog
  • python3 manage.py migrate blog

具體執行 migrate 的操作步驟,可以參見上一篇筆記。

blog/models.py 的具體內容如下:

# blog/models.py
from django.db import models


class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name


class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField()
    number_of_pingbacks = models.IntegerField()
    rating = models.IntegerField()


    def __str__(self):
        return self.headline

2、增

有以下幾種方法(以下操作皆在 python3 manage.py shell 環境中進行):

範例化,然後save() 儲存

from blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

當執行 save() 操作之後,資料就會建立到資料庫,因為主鍵 id 為自動增長的,所以id會自動賦值。

當然也可以先範例化一個空的 Blog,然後再賦值:

from blog.models import Blog
b = Blog()
b.name = 'hunter'
b.tagline = 'tag lines'
b.save()

save 之後,如果需要修改 name 的值,可以直接進行修改:

b.name = ‘python’
b.save()

使用 create() 方法建立

from blog.models import Blog
b = Blog.objects.create(name='hunter', tagline='tagline')

呼叫 create() 方法,會返回這條資料儲存後的物件。

批次建立
如果要批次建立資料,用上面的方法大概的就是在一個迴圈裡,挨個去範例化一個 Blog,然後執行 save() 操作。

但Django 提供了一個 bulk_create() 的方法,可以提高這個效率,使用範例如下:

from blog.models import Blog

blog_1 = Blog(name='hunter1', tagline='tagline1')
blog_2 = Blog(name='hunter2', tagline='tagline2')
blog_obj_list = [blog_1, blog_2]

Blog.objects.bulk(blog_obj_list)

3、查

查詢的語法有查詢之後返回 QuerySet 的查詢,比如 filter(),exclude()
也有 返回單個 object 的查詢,比如 get()

對於 QuerySet,這個我們可以簡單理解為是多個 object 範例形成的列表,但是這個列表是Django的一種特有的形式,具有能進行其他條件篩選的功能。

接下來簡單介紹一下查詢的功能:
filter(),過濾篩選,返回的是符合條件的資料
比如我們要搜尋 Entry 表裡,name 的值為 hunter 的資料,使用如下:

Entry.objects.filter(name='hunter')

exclude(),排除篩選,返回的是不符合條件的資料
比如我們要搜尋 Entry 表裡,name 的值不為 hunter 的資料:

Entry.objects.exclude(name='hunter')

鏈式查詢:
Django 支援 鏈式查詢,可以多個 filter 或者 exclude 條件累加,取的是 AND 的邏輯:

Entry.objects.filter(name='hunter').exclude(name='paul').filter(id=1)

懶載入:
Django 的查詢有一個機制叫做懶載入,意思是隻有當你真正需要去取資料的時候
系統才會去資料庫獲取資料,官方例子如下:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

上述語句雖然看起來查詢了三次資料庫,但實際上只有最後 print(q) 的時候才去存取了資料庫。

get()
前面講的 filter 和 exclude 返回的都是 QuerySet,簡單來說就是多個 object 形成的列表,而 get() 操作返回的直接是一條符合條件的 object。
比如:

blog = Blog.objects.get(id=1)

注意: get() 方法需要慎用,因為查詢的條件在資料庫裡,有多條或者一條都沒有的時候系統會報錯。
get() 的查詢一般僅用在我們能夠確定 在資料庫裡有且僅有一條資料情況下。

對QuerySe進行切片
用 filter 對資料進行操作的時候,如果需要對資料的返回數量進行限制,需要用到 python 裡的切片。
PS:數量的返回限制對應於 mysql 裡的 limit 用法。
比如:

blog_list = Blog.objects.all()[1:5]

但是和 python 裡的切片不一樣的時候,Django 的查詢不支援 負數查詢,比如下面的操作是不被允許的:

Blog.objects.all()[-1]  # error
Blog.objects.all()[-1: 3]  # error

欄位條件查詢:
在我們使用 mysql 的時候 where 後面會跟一些查詢的限制條件,在Django 裡用 雙下劃線來實現
比如 id 的值大於 5

Model.objects.filter(id__gt=5)

大於:gt
大於等於:gte
小於:lt
小於等於:lte
包含:in
是否為 null :isnull

精確查詢:
精確查詢使用 exact,一般查詢的時候 後面不加上面的欄位條件,都屬於精確查詢,不過預設是將 exact 欄位省略。
比如,下面兩條程式碼是一致的:

Blog.objects.get(id__exact=14)
Blog.objects.get(id=14) 

查詢外來鍵關聯資料
比如 Entry 這個 model 的外來鍵是 Blog,我們想通過 查詢 Blog 的 name 欄位為 Hunter 的Entry 資料:

Entry.objects.filter(blog__name='Hunter')

如果你想反向搜尋也是可以的,將 model 名稱小寫即可:

Blog.objects.filter(entry__headline='abc')

計算查詢
在Django 中參照欄位來進行比較,比如我們想實現如下功能:

select * from blog_entry where number_of_comments > number_of_pingbacks;

可以使用Django 中的 F,它的作用是 取值,取出其中的欄位值,那麼上述例子可以用 Django來實現可以是:

from django.db.models import F
Entry.objects.filter(number_of_comments__gt=F(「number_of_pinbbacks"))

還可以在使用中對 F() 進行一系列的操作:

Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)
Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))

pk 使用方法
pk 意思是 primary key ,主鍵,可以直接使用 pk 來搜尋,但在專案中一般是使用 id 作為主鍵,所以一般是等價於id的用法:

Blog.objects.filter(pk__gt=11)

Q 查詢:
我們知道可以使用 filter 來進行 鏈式查詢,那個邏輯是一個且的邏輯,那麼 或 的邏輯應該如何處理呢
我們可以使用Q() 來實現

我們可以使用 Q() 來將一個個的條件 串起來,比如,我們想篩選 Blog 中 id= 3 或者 id = 4 的資料可以使用如下:

Blog.objects.filter(Q(id=3) | Q(id=4))

也可以實現 且 的功能Q() & Q()
取反:~Q()

4、刪

如果要刪除 objects,有兩種方法,一種先獲取 object,然後 delete()

blog = Blog.objects.get(id=1)
blog.delete()

或者通過 filter 來 批次刪除:

Blog.objects.filter(id__gte=10).delete()

注意:如果有外來鍵關聯了 Blog,且 on_delete關係設定為 models.CASCADE,
那麼刪除相應的 Blog 的時候,對應的 關聯的 Entry 資料也會被刪除

5、改

批次更新:

Blog.objects.filter(id__gte=200).update(name='hunter')

單個更新:

blog = Blog.objects.get(id=1)
blog.name = ‘hunter’
blog.save()

以上就是我們這一篇筆記的全部內容,下一篇筆記將詳細介紹Django model裡的 各個欄位型別以及欄位屬性值。

本文首發於本人微信公眾號:Django筆記。

原文連結:Django筆記三之使用model對資料庫進行增刪改查

如果想獲取更多相關文章,可掃碼關注閱讀: