本文首發於公眾號:Hunter後端
原文連結:Django筆記二十七之資料庫函式之文字函式
這篇筆記將介紹如何使用資料庫函式里的文字函式。
顧名思義,文字函式,就是針對文字欄位進行操作的函式,如下是目錄彙總:
- Concat() —— 合併
- Left() —— 從左邊開始擷取
- Length() —— 獲取字串長度
- Lower() —— 小寫處理
- LPad() —— 從左邊填充指定字串
- MD5() —— 獲取字串MD5雜湊值
- Repeat() —— 重複指定欄位值
- Replace() —— 替換指定內容
- Reverse() —— 欄位內容反轉返回
- StrIndex() —— 獲取第一個匹配指定字串的下標
- SubStr() —— 字串擷取
- 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 系統操作的資料庫最佳化做一次彙總。
如果想獲取更多後端相關文章,可掃碼關注閱讀: