Django筆記二十七之資料庫函式之文字函式

XHunter發表於2023-04-22

本文首發於公眾號:Hunter後端
原文連結:Django筆記二十七之資料庫函式之文字函式

這篇筆記將介紹如何使用資料庫函式里的文字函式。

顧名思義,文字函式,就是針對文字欄位進行操作的函式,如下是目錄彙總:

  1. Concat() —— 合併
  2. Left() —— 從左邊開始擷取
  3. Length() —— 獲取字串長度
  4. Lower() —— 小寫處理
  5. LPad() —— 從左邊填充指定字串
  6. MD5() —— 獲取字串MD5雜湊值
  7. Repeat() —— 重複指定欄位值
  8. Replace() —— 替換指定內容
  9. Reverse() —— 欄位內容反轉返回
  10. StrIndex() —— 獲取第一個匹配指定字串的下標
  11. SubStr() —— 字串擷取
  12. Trim() —— 去除給定欄位空格

這一篇筆記記錄的函式有點多,可以慢慢看,慢慢測試,其中有一些函式是左右都有對應操作的,我這裡只介紹一個,另一個對應的函式除了函式名不一樣和作用相反外,用法都是一樣的。

我們這次用到的是 Author 這個 model:

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField(null=True, default=None)
    age = models.IntegerField(null=True, blank=True)
    alias = models.CharField(max_length=50, null=True, blank=True)
    goes_by = models.CharField(max_length=50, null=True, blank=True)

1、Concat() —— 合併

Concat() 函式,是合併的作用,接受至少兩個文字欄位或者表示式引數,將其合併成一個欄位返回。

示例如下:

from django.db.models.functions import Concat
from django.db.models import CharField, Value
from blog.models import Author

author = Author.objects.create(name="hunter", alias="alias")


author = Author.objects.annotate(
    concat_name=Concat('name', Value('_'), 'alias', output_field=CharField()
    )
).get(id=author.id)


print(author.concat_name)

在示例中,我們將 name 欄位和 alias 欄位以及 _ 這個字串用 Value() 函式修飾,傳入 Concat(),並透過 output_field 來指定輸出字串型別,將三者合併成一個字串返回

注意: 如果是將 TextField() 和 CharField() 欄位進行合併,那麼 output_field 必須是 TextField()

2、Left() —— 從左邊開始擷取

輸入兩個引數,一個是指定欄位,一個是指定的長度,表示將對該欄位從左邊開始擷取指定長度返回

以下是示例:

from django.db.models.functions import Left

author = Author.objects.annotate(left_three_str=Left('name', 3)).get(id=10)

print(author.left_three_str)

注意一下,我在示例中使用到的 id 的值都是在我自己資料庫的 id值,讀者在自己測試的時候,需要替換成自己資料的真實 id

同理,django.db.models.functions.Right 是從右邊開始擷取

3、Length() —— 獲取字串長度

接受文字欄位或者表示式作為引數,返回字串長度

如果欄位或者表示式為 null,那麼在 Python 裡會返回 None

以下是使用示例:

from django.db.models.functions import Length

author = Author.objects.annotate(name_length=Length("name"), email_length=Length("email")).get(id=10)

print(author.name_length)
# 返回數字

print(author.email_length)
# 欄位值為 null, 所以返回 None

這裡也可以用於搜尋,假設說我想搜尋 name 欄位長度大於3的資料,可以如下實現:

from django.db.models import CharField
from django.db.models.functions import Length

CharField.register_lookup(Length)

authors = Author.objects.filter(name__length__gt=3)
print(authors.count())

或者 annotate() 出一個新欄位,然後進行 filter()

Author.objects.annotate(name_length=Length("name")).filter(name_length__gt=3)

4、Lower() —— 小寫處理

接受文字欄位名或者表示式作為引數傳入,然後將其小寫化處理返回

以下是使用示例:

from django.db.models.functions import Lower

Author.objects.create(name="HUNTER")

author = Author.objects.annotate(name_lower=Lower("name")).get(id=11)

print(author.name_lower)

跟 Length() 函式一樣,也可以使用註冊的方式來搜尋:

from django.db.models import CharField
from django.db.models.functions import Lower

CharField.register_lookup(Lower)

authors = Author.objects.filter(name__lower="hunter")
print(authors.values("name"))

同理,大寫化的函式為 django.db.models.functions.Upper()

5、LPad() —— 從左邊填充指定字串

LPad() 意思為從左邊填充指定字串,接受三個引數:

第一個引數為欄位名或表示式

第二個引數為需要填充到的長度,引數名為 length,需要指定值

第三個引數名為 fill_text,值為填充的內容,預設為空字串

假設我們需要將 abc 填充到 name 欄位,需要填充到 10 個字元長度

那麼如果 name 的原始值為 hunter,結果則會是 abcahunter

如果需要填充的值短了,那麼就會重複填充,如果長了,就會被擷取填充,在剛剛的例子裡,第二次填充的時候,再重複一次 abc 則超出 10個長度的限制,所以 abc 被擷取了。

以下是使用示例:

from django.db.models.functions import LPad
from django.db.models import Value

Author.objects.create(name="HUNTER")

author = Author.objects.annotate(
    name_1=LPad('name', 4, fill_text=Value('abc')),
    name_2=LPad('name', 8, fill_text=Value('abc')),
    name_3=LPad('name', 16, fill_text=Value('abc'))
).get(id=11)


print(author.name_1)
# HUNT

print(author.name_2)
# abHUNTER

print(author.name_3)
# abcabcabcaHUNTER

更新操作

我們還可以利用 LPad() 函式來對欄位進行更新操作

Author.objects.filter(id=11).update(name=LPad('name', 10, Value('abv')))
author = Author.objects.get(id=11)
print(author.name)

這段程式碼的含義為,將 name 欄位原有值的左邊填充 abc 字串填充到10個字元長度後更新到 name 欄位

同理,還有一個從右邊開始填充的函式 RPad(),也是同樣的用法

6、MD5() —— 獲取字串MD5雜湊值

接受單個文字欄位或者表示式作為引數,返回字串的 MD5 雜湊值

from django.db.models.functions import MD5

author = Author.objects.annotate(name_md5=MD5('name')).get(id=11)

print(author.name_md5)

7、Repeat() —— 重複指定欄位值

Repeat(expression, number)
接受欄位引數,和重複的次數,返回欄位內容重複 number 遍之後的資料

from django.db.models.functions import Repeat

Author.objects.create(name="Python")
# id = 13

author = Author.objects.annotate(repeat_name=Repeat("name", 3)).get(id=13)
print(author.repeat_name)

# 列印出的值為:PythonPythonPython

更新欄位資料

將 id=13 的資料的 name 欄位重複三遍之後更新到該欄位:

Author.objects.filter(id=13).update(name=Repeat("name", 3))

8、Replace() —— 替換指定內容

Replace(expression, text, replacement=Value(''))
替換,即將 expression 欄位的值的所有內容為 text 的替換成 replacement 的內容,replacement 預設為空字串

在下面的例子中,我們將 name 欄位中所有的 Ma 字串更新為 Je

from django.db.models.functions import Replace
from django.db.models import Value

Author.objects.create(name="Match-Mary")
# id = 14

Author.objects.filter(id=14).update(name=Replace('name', Value('Ma'), Value('Je')))

author = Author.objects.get(id=14)

print(author.name)
# Jetch-Jery

9、Reverse() —— 欄位內容反轉返回

接受欄位或者表示式為引數,將原欄位內容倒序後返回

from django.db.models.functions import Reverse

author = Author.objects.annotate(reverse_name=Reverse('name')).get(id=11)
print(author.reverse_name)

10、StrIndex() —— 獲取第一個匹配指定字串的下標

接受兩個引數,一個引數為欄位名,第二個引數為需要匹配的子串

如果子串在欄位中被匹配上了,將會返回第一個匹配上的子串的下標

注意1:匹配上的下標是從1開始計數的,如果沒有匹配上,那就回返回0

注意2:這個匹配的過程是忽略大小寫的

from django.db.models.functions import StrIndex
from django.db.models import Value

author = Author.objects.create(name="thIs is a Test")

author = Author.objects.annotate(
    is_index=StrIndex("name", Value("is")),
    test_index=StrIndex("name", Value("test")),
    xx_index=StrIndex("name", Value("xx"))
).get(id=author.id)


print(author.is_index)
# 3,is 字串匹配忽略大小寫,下標從1開始,所以是3

print(author.test_index)
# 11 

print(author.xx_index)
# 0 找不到對應的字串,所以返回 0,可以根據 0 這個標誌位來判斷欄位中是否包含某個特定字元

而這個操作我們可以用來篩選欄位中是否包含某個特定字串的資料,根據返回的結果是否為 0 來判斷:

authors = Author.objects.annotate(ter_index=StrIndex("name", Value("ter"))).filter(ter_index__gt=0)
print(authors.count())

11、SubStr() —— 字串擷取

SunStr(expression, pos, length=None)

這是一個字串擷取的函式,給定一個欄位名,和開始的下標(下標從1開始計數),和需要計數的長度

表示將某欄位,從指定下標開始,擷取指定長度的字串


from django.db.models.functions import Substr

# 將 name 欄位 從 第二個字元開始往後擷取三個長度的字元
author = Author.objects.annotate(name_sub_str=Substr('name', 2, 3)).get(id=12)

print(author.name_sub_str)

可以用於直接更新:

Author.objects.filter(id=12).update(name=Substr('name', 2, 3))

12、Trim() —— 去除給定欄位空格

去除空格給定欄位左右兩邊的空格

Author.objects.create(name=" test trim ")  # id = 15

from django.db.models.functions import Trim

author = Author.objects.annotate(trim_name=Trim("name")).get(id=15)

print(author.trim_name)

也可以直接用於更新:

Author.objects.filter(id=15).update(name=Trim("name"))

同理,還有去除左邊空格的函式 LTrim() 和 去除右邊空格的函式 RTrim()

以上就是本篇筆記全部內容,下一篇將會是比較重要也比較長的一篇筆記,將會對 Django 系統操作的資料庫最佳化做一次彙總。

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

image

相關文章