Django 2.2 使用 PyMySQL 时的常见报错与修复方案
本文详解Django 2.2在Python 3环境下使用PyMySQL替代mysqlclient时遇到的两个典型错误:一是版本校验失败导致的ImproperlyConfigured异常,二是字符串类型缺少decode方法引发的TypeError。通过修改Django源码或引入force_str函数,可有效解决这些兼容性问题,确保项目正常运行。
Django 2.2 使用 PyMySQL 时的常见报错与修复方案
由于Django默认的MySQLdb库不支持Python 3,开发者通常采用PyMySQL库进行替代,但这往往会导致一系列兼容性问题。特别是在执行以下两条命令时,容易遇到阻碍:
执行迁移或 inspectdb 命令
python manage.py makemigrations
or
python manage.py inspectdb
错误一:mysqlclient 版本过低报错
第一个坑(提示你的mysqlclient版本过低)
无论你是否通过pip install mysqlclient安装了最新版,系统均会抛出如下错误:
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None
遇到此类报错确实令人沮丧,此时可尝试参考网络上的解决方案,即采用注释相关代码的方式来解决。
定位到Python安装路径下的Python36-32\Lib\site-packages\django\db\backends\mysql\base.py文件。
对该文件中的特定代码段进行注释(操作前建议先关闭PyCharm IDE以避免文件占用)。
if version < (1, 3, 3):
raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)
错误二:str 类型缺少 decode 方法
第二个坑(str类型没有decode方法)
在Python 3中,str类型默认即为unicode编码,需通过encode方法转换为bytes类型后,bytes对象才具备decode解码方法。报错来源指向:Python36\lib\site-packages\django\db\backends\mysql\operations.py,第149行的last_executed_query函数。
网络上常见的解决方案是将encode改为decode,但这种做法逻辑混乱。以下是Django 2.2.1原版中该方法的实际内容:
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.
query = getattr(cursor, '_executed', None)
if query is not None:
query = query.decode(errors='replace')
return query
通过print语句输出query结果,其数据类型显示为str。
SELECT @@SQL_AUTO_IS_NULL
数据类型为str
网上还有建议直接注释if判断语句的“注释大法”,但由于不确定注释后是否会产生其他副作用,此处不予采纳。
随后查阅Django GitHub仓库中该文件最新及历史版本,发现master分支的内容已更新如下:
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')
观察函数名可知,其目的是强制将SQL查询结果转换为字符串类型。
解决方案:引入 force_str 函数
值得注意的是,Django官网发布的2.2.1/2.2.2版本(当时最新版)并未包含此修复,这可能导致用户困惑。因此,需要在该文件上方引入相关方法。
from django.utils.encoding import force_str
完成上述修改后,再次执行manage.py命令,问题即可解决。
以上内容为本文的全部总结,希望能为读者的学习提供有益帮助,同时也欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









