2012-10-29 17 views
2

可能重複:
How to filter (or replace) unicode characters that would take more than 3 bytes in UTF-8?Django的與MySQL和UTF-8

背景:

我使用Django與MySQL 5.1和我有4麻煩字節在我的Web應用程序中導致致命錯誤的UTF-8字符。

我已經使用a script將我數據庫中的所有表和列轉換爲UTF-8,它修復了大多數unicode問題,但仍然存在4字節unicode字符的問題。由於noted elsewhere,MySQL 5.1不支持長度超過3個字節的UTF-8字符。

每當我在我的Django的網站上輸入一個4字節Unicode字符(例如)成的ModelForm形式驗證,然後類似以下的異常引發:

Incorrect string value: '\xF0\x9F\x80\x90' for column 'first_name' at row 1 

我的問題:

在Django Web應用程序中使用MySQL 5.1數據庫避免由4字節UTF-8字符引起的致命錯誤的合理方法是什麼?

我已經考慮:

  1. 有選擇地停止MySQL的警告,以避免明確該錯誤信息(不知道這是否可行還)
  2. 創建中間件將尋找通過request.POSTQueryDict和替代/刪除所有無效的UTF8字符
  3. 以某種方式hook/alter/monkey在執行查詢之前爲輸出SQL查詢的機制輸出Django或MySQLdb以替換/刪除所有無效的UTF-8字符

例中間件替換無效字符(由this SO question啓發):

import re 

class MySQLUnicodeFixingMiddleware(object): 

    INVALID_UTF8_RE = re.compile(u'[^\u0000-\uD7FF\uE000-\uFFFF]', re.UNICODE) 

    def process_request(self, request): 
     """Replace 4-byte unicode characters by REPLACEMENT CHARACTER""" 
     request.POST = request.POST.copy() 
     for key, values in request.POST.iterlists(): 
      request.POST.setlist(key, 
       [self.INVALID_UTF8_RE.sub(u'\uFFFD', v) for v in values]) 

回答

1

你有一個選項來升級的MySQL?如果這樣做,則可以升級並將編碼設置爲utf8mb4。

假設你沒有選擇,我看到你的這些選項:

1)添加Java腳本/前端驗證,以防止以外的任何其他1,2或3個字節Unicode字符的輸入,

2)補充,以在模型中的清理功能剝去的任何4字節Unicode字符的數據(這將是您的選項2或3)

與此同時,它看起來像您的用戶實際上使用4個字節的字符。如果有在您的應用程序中使用它們的商業案例,那麼您可以轉到要求升級的權力。