Django2.x配置mysql

SilenceHL發表於2021-04-04

宣告:以下內容均為我個人的理解,如果發現錯誤或者疑問可以聯絡我共同探討

簡介

在Django中使用mysql資料庫是很常見的,但是升級到Django2.0以後,已經不支援Python2.x,mysql的配置也需要隨之改變

配置

配置settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dbname',
        'USER': 'dbuser',
        'PASSWORD': 'dbpassword',
        'HOST':'dbhost',
        'PORT':'dbport'
    }
}

使用pymysql

由於安裝mysqlclient不支援python3,所以使用pymysql包,安裝pymysql並匯入

pip install pymysql

配置pymysql,在settings.py所在的目錄下的__init__.py檔案中匯入

import pymysql
pymysql.install_as_MySQLdb()

修改原始碼中的問題

  • 由於在python3中不在使用mysqlclient,所以原始碼中限制mysqlclient版本這一程式碼就不適用於現在的環境

    檔案路徑django\db\backends\mysql\base.py,將版本限制異常給註釋掉在檔案的第35-36行

    # if version < (1, 3, 13):
    #     raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
  • 由於python2的str是位元組流(類似於bytes型別)需要通過decode轉換成unicode型別才能使用,但在python3中str預設unicode型別不需要轉換且沒有decode解碼所以要將這裡的程式碼修改。在最新的Django原始碼中已經將這裡修改了(可以通過Django官網或github檢視),在最新的原始碼中使用django.utils.encoding中force_str方法解決了該問題,force_str方法實際上是force_text方法,force_text方法通過判斷傳入引數的型別後將型別轉為unicode型別的str之後返回

    \django\utils\encoding.py
    ······
    def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
        """
        Similar to smart_text, except that lazy instances are resolved to
        strings, rather than kept as lazy objects.
    
        If strings_only is True, don't convert (some) non-string-like objects.
        """
        # Handle the common case first for performance reasons.
        if issubclass(type(s), str):
            return s
        if strings_only and is_protected_type(s):
            return s
        try:
            if isinstance(s, bytes):
                s = str(s, encoding, errors)
            else:
                s = str(s)
        except UnicodeDecodeError as e:
            raise DjangoUnicodeDecodeError(s, *e.args)
        return s

    最後修改\django\db\backends\mysql\operations.py檔案中的last_executed_query方法(記得匯入force_str)

        from django.utils.encoding import force_str
        ···
        def last_executed_query(self, cursor, sql, params):
            # With MySQLdb, cursor objects have an (undocumented) "_executed"
            # attribute where the exact query sent to the database is saved.
            # See MySQLdb/cursors.py in the source distribution.
            # MySQLdb returns string, PyMySQL bytes.
            return force_str(getattr(cursor, '_executed', None), errors='replace')
本作品採用《CC 協議》,轉載必須註明作者和本文連結