免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
刨根問底,完美解決Django2版本連接MySQL報錯的問題

引子

關(guān)于Django2版本連接MySQL發(fā)生的問題以及修改源碼的解決方法參考下面這篇文章:

Django與MySQL的交互

但是,上面這種修改源碼的方法在生產(chǎn)環(huán)境中使用的話會有很多問題。

本文為大家詳細講解如何在不修改Django源碼的情況下解決這個問題。

Django中的源碼解析

我們來看一下我們使用的Python解釋器(可以是全局的也可以是虛擬環(huán)境的)中django包有關(guān)MySQL配置的源碼。

源碼位置是:

(你的Python解釋器安裝目錄或者虛擬環(huán)境目錄)\django21\Lib\site-packages\django\db\backends\mysql\base.py

這個base.py文件中的內(nèi)容有點多,我們把最關(guān)鍵的部分挑出來解釋一下:

"""
MySQL database backend for Django.

Requires mysqlclient: https://pypi.org/project/mysqlclient/  # 之前沒安裝的話得從pypi中下載mysqlclient包
"""
import re

from django.core.exceptions import ImproperlyConfigured
from django.db import utils
from django.db.backends import utils as backend_utils
from django.db.backends.base.base import BaseDatabaseWrapper
from django.utils.functional import cached_property

try:
    import MySQLdb as Database  # 導(dǎo)入MySQLdb模塊
except ImportError as err:
    raise ImproperlyConfigured(
        'Error loading MySQLdb module.\n'
        'Did you install mysqlclient?'
    ) from err

from MySQLdb.constants import CLIENT, FIELD_TYPE                # isort:skip
from MySQLdb.converters import conversions                      # isort:skip

# Some of these import MySQLdb, so import them after checking if it's installed.
from .client import DatabaseClient                          # isort:skip
from .creation import DatabaseCreation                      # isort:skip
from .features import DatabaseFeatures                      # isort:skip
from .introspection import DatabaseIntrospection            # isort:skip
from .operations import DatabaseOperations                  # isort:skip
from .schema import DatabaseSchemaEditor                    # isort:skip
from .validation import DatabaseValidation                  # isort:skip

version = Database.version_info
# 打印一下這個version
print("version>>>>>>",version)

if version < (1, 3, 7):
    raise ImproperlyConfigured('mysqlclient 1.3.7 or newer is required; you have %s.' % Database.__version__)

###################
and so on...

我們可以看到,源碼中對MySQLdb模塊的版本進行了限制!

django1.11.20版本對MySQLdb的version的限制

在django1.11.20版本中的version限制是1.2.3以上:

django2.1及以上對MySQLdb的version的限制

是1.3.7以上:

成功運行程序時打印的版本

項目成功運行的話,MySQLdb的版本必須大于1.3.7才可以:

所以:解決這個問題的關(guān)鍵在于得解決本機MySQLdb模塊的版本!用django2的話必須大于1.3.7!

MySQLdb模塊的問題

還是在Django源碼里面,我們打印一下這個Database(其實就是MySQLdb):

try:
    import MySQLdb as Database
    # 打印一下這個Database
    print(Database,type(Database))
except ImportError as err:
    raise ImproperlyConfigured(
        'Error loading MySQLdb module.\n'
        'Did you install mysqlclient?'
    ) from err

結(jié)果出乎意料?。?!

是的!你沒有看錯!顯示的模塊竟然是:pymysql(打印2次是在DEBUG模式下的設(shè)置)?。?!

這里才是解決問題的關(guān)鍵所在!

pymysql源碼解析 ***

然后大家回過頭來想一下,我們配置的時候,在與項目同名的那個模塊的__init__.py文件中加入了2行與pymysql相關(guān)的代碼:

import pymysql  # 導(dǎo)入模塊相當于執(zhí)行了這個包中的__init__.py文件

pymysql.install_as_MySQLdb()  # 執(zhí)行pymysql的install_as_MySQLdb方法

然后我們來看一下當前虛擬環(huán)境中安裝的pymysql包中的__init_.py文件的源碼:

"""
PyMySQL: A pure-Python MySQL client library.

### 說明略去
"""
import sys

from ._compat import PY2
from .constants import FIELD_TYPE
from .converters import escape_dict, escape_sequence, escape_string
from .err import (
    Warning, Error, InterfaceError, DataError,
    DatabaseError, OperationalError, IntegrityError, InternalError,
    NotSupportedError, ProgrammingError, MySQLError)
from .times import (
    Date, Time, Timestamp,
    DateFromTicks, TimeFromTicks, TimestampFromTicks)

# pymysql的版本
VERSION = (0, 9, 3, None)
if VERSION[3] is not None:
    VERSION_STRING = "%d.%d.%d_%s" % VERSION
else:
    VERSION_STRING = "%d.%d.%d" % VERSION[:3]
threadsafety = 1
apilevel = "2.0"
paramstyle = "pyformat"


class DBAPISet(frozenset):

    # 省略

# 省略 def Binary(x): """Return x as a binary type.""" # 省略

def Connect(*args, **kwargs): """ Connect to the database; see connections.Connection.__init__() for more information. """ # 省略

from . import connections as _orig_conn if _orig_conn.Connection.__init__.__doc__ is not None: Connect.__doc__ = _orig_conn.Connection.__init__.__doc__ del _orig_conn def get_client_info(): # for MySQLdb compatibility version = VERSION if VERSION[3] is None: version = VERSION[:3] return '.'.join(map(str, version)) connect = Connection = Connect # we include a doctored version_info here for MySQLdb compatibility version_info = (1, 3, 12, "final", 0) NULL = "NULL" __version__ = get_client_info() def thread_safe(): return True # match MySQLdb.thread_safe()

### 這里是最關(guān)鍵的 def install_as_MySQLdb(): """ After this function is called, any application that imports MySQLdb or _mysql will unwittingly actually use pymysql. """
### 導(dǎo)入MySQLdb、_mysql其實相當于導(dǎo)入了pymysql模塊?。?! sys.modules["MySQLdb"] = sys.modules["_mysql"] = sys.modules["pymysql"]
__all__ = [ # 略去 ]

其中有個地方十分關(guān)鍵,根據(jù) install_as_MySQLdb 函數(shù)中的內(nèi)容可以看到:

在這個環(huán)境中導(dǎo)入MySQLdb模塊相當于導(dǎo)入了pymysql模塊。

也就是說,在Django的那個base.py文件中的  version = Database.version_info,其實用的是pymysql.version_info,從pymysql的源碼中我們可以看到,里面的version_info的值為(1, 3, 12, 'final', 0),跟我們上圖中打印的結(jié)果是一樣的!

這也就解釋了了為什么我們打印Database的時候顯示的竟然是pymysql模塊。

使用合適的pymysql的版本解決

通過上面的源碼分析,相信聰明的你已經(jīng)想出了解決方案了:針對不同版本的Django使用對應(yīng)版本的pymysql模塊就可以了!

從上面pymysql的源碼可以看到:pymysql的版本是 VERSION為0.9.3,對應(yīng)的MySQLdb的版本設(shè)置成了1.3.12,比規(guī)定的1.3.7高,可以解決報錯問題!

使用pypi安裝指定版本的pymysql

當然,在聯(lián)網(wǎng)的情況下,我們可以直接使用pip安裝指定版本的pymysql:

pip install pymysql==0.9.3 -i https://pypi.douban.com/simple

實際中大家的服務(wù)器可能會禁止連接外網(wǎng),下面為大家介紹一下使用pypi安裝的方法。

進入pypi官網(wǎng)搜索對應(yīng)的模塊

pypi的官網(wǎng)為:https://pypi.org/

然后搜索對應(yīng)的模塊:

尋找對應(yīng)的版本

找到對應(yīng)的版本 

點擊DownloadFiles

選擇不同格式的文件

文件的格式基本都是 *.whl 或者 *.tar.gz

使用scp命令傳遞文件

Linux scp命令

whl文件與tar包的安裝方法

whl文件的安裝方法

[root@mycentos ~]# /opt/py3.6/ve1/bin/pip  install  xxx.whl

tar包的安裝方法

先解壓并進入目錄

tar -xzvf  xxx.tar.gz
cd xxx

執(zhí)行安裝命令 (虛擬環(huán)境中安裝的話需要使用虛擬環(huán)境的目錄)

/opt/py3.6/ve1/bin/python setup.py install

大功告成!

后記:關(guān)于Django2.2版本的問題

我試了一下,使用Django2.2版本的話,需要的MySQldb版本是 1.3.13,而0.9.3版本的pymysql不能支持,還是會報錯的:

所以實際中建議大家選擇合適的Django版本開發(fā)。

在init文件中設(shè)置pymysql的version_info —— 仍需要修改源碼

也許聰明的你會想到這樣的方案:我們在__init__.py文件中導(dǎo)入pymysql模塊后可以設(shè)置一下pymysql的version_info值不就可以了嗎:

import pymysql

### 自己設(shè)置pymysql的version_info
pymysql.version_info  = (1, 3, 15, "final", 0)

pymysql.install_as_MySQLdb()

雖然這樣做可以通過“版本的判斷”,但是運行程序的時候還是報異常了(Django2.2.10版本 + pymysql0.9.3版本測試):

我們看看源碼報錯的位置以及修改的方法:

 

將decode修改成encode就好了:

 

不過本人不推薦這樣的修改方式:既然Django在這里做了限制說明是強制要求我們使用新版本的pymysql的,如果實際中強制修改的話業(yè)務(wù)在后續(xù)的維護過程中可能會發(fā)生問題,所以實際中還是建議大家使用合適的版本進行開發(fā)工作!

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
?mac端python3 django連接mysql數(shù)據(jù)庫問題
那些年在win下填過的Django坑
windows上python和django開發(fā)環(huán)境的安裝和配置
Nginx+uWsgi+Django+Python+MongoDB+mySQL服務(wù)器搭建
Django 入門篇2:初始化項目
4 種 Python 連接 MySQL 數(shù)據(jù)庫的方法
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服