django 1.5 + pymysql 错误:ImportError: 无法导入名称 Thing2Literal

5 投票
2 回答
3735 浏览
提问于 2025-04-17 18:31

我尝试使用django1.5,并且想用pymysql来替代MySQLdb,具体方法可以参考这里如何让Django与不支持的MySQL驱动一起工作,比如gevent-mysql或Concurrence的MySQL驱动?

在我的管理命令的开头:

+try:
+    import pymysql
+    pymysql.install_as_MySQLdb()
+except ImportError:
+    pass 

但是出现了错误:

/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 30, in <module>
    from MySQLdb.converters import conversions, Thing2Literal
ImportError: cannot import name Thing2Literal

该怎么解决呢?

2 个回答

2

MySQLdb 中,如果你使用的是较新版本的 MySQL,就不会用到 Thing2Literal 方法。这种情况下,当连接可用时,会使用连接的 string_literal 方法。

你需要对 pymysql 进行一些修改,以便它也能这样做,并允许你使用连接的方法。

背景

这个方法是用来处理 SQL 语句中的特殊字符的。随意使用它可能会带来安全问题,这一点你需要考虑。

你想使用连接的方法的原因是字符集(charset),它在处理特殊字符时起着重要作用。

解决 ImportError 问题

这个问题比较简单,你只需要在 pymysql.converters 中实现一个虚拟的 Thing2Literal 方法。反正我们不会调用它,所以不需要太在意:

def _Thing2Literal(o,d):
    """
    Implemented for compatibility with Django.
    This function is overriden by the connection's escape method when one is available.
    """
    raise NotImplementedError('Thing2Literal is only implemented through the Connection object.')

 Thing2Literal = _Thing2Literal

在连接可用时动态修改 Thing2Literal

pymysql.connections.Connection 中,添加:import pymysql.converters

pymysql.connections.Connection.__init__ 的末尾,添加以下内容:

pymysql.converters.Thing2Literal = lambda o, d: self.escape(o)

pymysql.connections.Connection.__del__ 的末尾,添加相反的内容:

pymysql.converters.Thing2Literal = pymysql.converters._Thing2Literal

我们可以忽略 d 参数,因为它是一个包含现有转换的字典,这些转换已经可以通过 Connection.escape 方法使用。

注意事项

这可能会导致问题,并暴露出安全隐患。
此外,如果你有多个活动连接使用 不同 的字符集,这可能会出现严重的问题。


你可能还需要对 Django 进行一些调整,以确保它在可用时使用你修改过的版本——也就是说,把 from MySQLdb.converters import Thing2Literal 替换成其他内容,以便仍然将 Thing2Literal 绑定到模块。

当然,你也可以通过不修改 Django,而让 _Thing2Literal 函数更聪明来实现同样的效果。

3

我刚刚在使用Django 1.5.1和PyMySQL 0.5的时候遇到了同样的问题。

我通过使用CMGS的一个分支版本(https://github.com/CMGS/PyMySQL)来解决了这个问题。希望这个改进能被纳入到主版本的PyMySQL中。你可以在这里查看CMGS的请求:https://github.com/petehunt/PyMySQL/pull/106

根据作者的评论和在请求中的反馈,我觉得这个版本在生产环境中使用是相当可靠的。

下面是一个requirements.txt文件中的示例行:

-e git://github.com/CMGS/PyMySQL.git#egg=PyMySQL-dev

撰写回答