Unicode 資料¶
Django 在任何地方都支援 Unicode 資料。
這份文件告訴您,如果您正在撰寫使用非 ASCII 編碼的資料或範本的應用程式,您需要知道什麼。
建立資料庫¶
請確保您的資料庫已設定為能夠儲存任意字串資料。通常,這表示給予它 UTF-8 或 UTF-16 的編碼。如果您使用更嚴格的編碼(例如,latin1 (iso8859-1)),您將無法在資料庫中儲存某些字元,並且資訊將會遺失。
MySQL 使用者,請參閱 MySQL 手冊,以了解如何設定或變更資料庫字元集編碼的詳細資訊。
PostgreSQL 使用者,請參閱 PostgreSQL 手冊,以了解如何建立具有正確編碼的資料庫的詳細資訊。
Oracle 使用者,請參閱 Oracle 手冊,以了解如何設定(第 2 節)或變更(第 11 節)資料庫字元集編碼的詳細資訊。
SQLite 使用者,您無需執行任何操作。SQLite 始終使用 UTF-8 進行內部編碼。
所有 Django 的資料庫後端都會自動將字串轉換為與資料庫通訊的適當編碼。它們也會自動將從資料庫檢索的字串轉換為字串。您甚至不需要告訴 Django 您的資料庫使用哪種編碼:這是透明地處理的。
如需更多資訊,請參閱下面的「資料庫 API」章節。
一般字串處理¶
每當您在 Django 中使用字串時(例如,在資料庫查詢、範本呈現或任何其他地方),您有兩種選擇來編碼這些字串。您可以使用正常字串或位元組字串(以 ‘b’ 開頭)。
警告
位元組字串不攜帶任何有關其編碼的資訊。因此,我們必須進行假設,而 Django 假設所有位元組字串都是 UTF-8 編碼。
如果您將以其他格式編碼的字串傳遞給 Django,事情將會以有趣的方式出錯。通常,Django 會在某個時間點引發 UnicodeDecodeError
。
如果您的程式碼僅使用 ASCII 資料,則可以安全地使用您的正常字串,隨意傳遞它們,因為 ASCII 是 UTF-8 的子集。
不要被誤導,認為如果您的 DEFAULT_CHARSET
設定設定為 'utf-8'
以外的其他值,您就可以在位元組字串中使用其他編碼!DEFAULT_CHARSET
僅適用於範本呈現(和電子郵件)產生的字串。Django 始終假設內部位元組字串使用 UTF-8 編碼。這樣做的原因是 DEFAULT_CHARSET
設定實際上不受您(如果您是應用程式開發人員)的控制。它受安裝和使用您應用程式的人員的控制 – 如果該人員選擇不同的設定,您的程式碼仍然必須繼續運作。因此,它不能依賴該設定。
在大多數情況下,當 Django 處理字串時,它會先將它們轉換為字串,然後再執行其他任何操作。因此,作為一般規則,如果您傳入位元組字串,請準備好在結果中接收返回的字串。
翻譯後的字串¶
除了字串和位元組字串之外,當您使用 Django 時,您可能會遇到第三種類似字串的物件。該框架的國際化功能引入了「惰性翻譯」的概念 – 一個已標記為翻譯的字串,但其實際翻譯結果要等到該物件在字串中使用時才會確定。此功能在翻譯地區設定在字串使用之前未知的情況下非常有用,即使字串可能最初是在首次匯入程式碼時建立的。
通常,您不必擔心惰性翻譯。只要知道如果您檢查一個物件,並且它聲稱是 django.utils.functional.__proxy__
物件,那麼它就是惰性翻譯。使用惰性翻譯作為引數呼叫 str()
將會產生目前地區設定的字串。
有關惰性翻譯物件的更多詳細資訊,請參閱 國際化 文件。
有用的實用函式¶
由於某些字串操作會不斷重複出現,因此 Django 隨附了一些有用的函式,這些函式應該可以讓處理字串和位元組字串物件變得更容易一些。
轉換函式¶
django.utils.encoding
模組包含一些方便在字串和位元組字串之間來回轉換的函式。
smart_str(s, encoding='utf-8', strings_only=False, errors='strict')
將其輸入轉換為字串。encoding
參數指定輸入編碼。(例如,Django 在處理表單輸入資料時在內部使用此功能,這些資料可能不是 UTF-8 編碼的。)如果將strings_only
參數設定為 True,則 Python 數字、布林值和None
將不會轉換為字串(它們會保留其原始類型)。errors
參數採用 Pythonstr()
函式用於錯誤處理的任何值。force_str(s, encoding='utf-8', strings_only=False, errors='strict')
在幾乎所有情況下都與smart_str()
相同。不同之處在於第一個引數是 惰性翻譯 實例。雖然smart_str()
保留惰性翻譯,但force_str()
會強制將這些物件轉換為字串(導致翻譯發生)。通常,您會想要使用smart_str()
。但是,force_str()
在絕對必須擁有字串才能運作的範本標籤和篩選器中很有用,而不僅僅是可以轉換為字串的東西。smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict')
本質上與smart_str()
相反。它會強制將第一個引數轉換為位元組字串。strings_only
參數的行為與smart_str()
和force_str()
相同。這與 Python 內建的str()
函式略有不同,但 Django 內部的一些地方需要這種差異。
通常,您只需要使用 force_str()
。盡可能早地在任何可能是字串或位元組字串的輸入資料上呼叫它,從那時起,您可以將結果視為始終是字串。
URI 和 IRI 處理¶
網頁框架必須處理 URL(這是一種 IRI)。URL 的一個要求是它們僅使用 ASCII 字元進行編碼。但是,在國際環境中,您可能需要從 IRI 建構 URL – 粗略地說,是可能包含 Unicode 字元的 URI。使用這些函式來引用並將 IRI 轉換為 URI
注意
一個範例可以更清楚地說明
>>> from urllib.parse import quote
>>> from django.utils.encoding import iri_to_uri
>>> quote("Paris & Orléans")
'Paris%20%26%20Orl%C3%A9ans'
>>> iri_to_uri("/favorites/François/%s" % quote("Paris & Orléans"))
'/favorites/Fran%C3%A7ois/Paris%20%26%20Orl%C3%A9ans'
一個範例來示範
>>> from django.utils.encoding import uri_to_iri
>>> uri_to_iri("/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93")
'/♥♥/?utf8=✓'
>>> uri_to_iri("%A9hello%3Fworld")
'%A9hello%3Fworld'
iri_to_uri(iri_to_uri(some_string)) == iri_to_uri(some_string)
uri_to_iri(uri_to_iri(some_string)) == uri_to_iri(some_string)
因此,你可以安全地在同一個 URI/IRI 上多次呼叫它,而無需擔心雙重引號的問題。
模型¶
from urllib.parse import quote
from django.utils.encoding import iri_to_uri
def get_absolute_url(self):
url = "/person/%s/?x=0&y=0" % quote(self.location)
return iri_to_uri(url)
範本¶
手動建立範本時請使用字串
from django.template import Template
t2 = Template("This is a string template.")
檔案¶
import sys
sys.getfilesystemencoding()
這應該輸出「UTF-8」。
在你的開發環境中,你可能需要在你的 ~/.bashrc
中新增類似於以下的設定:
export LANG="en_US.UTF-8"
表單提交¶
def some_view(request):
# We know that the data must be encoded as KOI8-R (for some reason).
request.encoding = "koi8-r"
...
你甚至可以在存取 request.GET
或 request.POST
之後變更編碼,而所有後續的存取都將使用新的編碼。