django 1.5 + error pymysql: ImportError: no se puede importar el nombre Thing2Literal

Intento usar django1.5 y pymysql como MySQLdb como aquí ¿Cómo hacer que Django funcione con controladores MySQL no compatibles como gevent-mysql o el controlador MySQL de Concurrence?

En la parte superior de mi comando de gestión:

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

pero obtener error:

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

¿Como arreglarlo?

Simplemente se encontró con el mismo problema en Django 1.5.1 y PyMySQL 0.5

Se solucionó mediante el uso de la bifurcación CMGS ( https://github.com/CMGS/PyMySQL ) de PyMySQL. Esperemos que esto sea un camino para PyMySQL. Consulte la solicitud de extracción de CMGS aquí: https://github.com/petehunt/PyMySQL/pull/106

A juzgar por los comentarios del autor y los comentarios en la solicitud de extracción, creo que es bastante sólido para el uso de producción.

Ejemplo de línea Requirements.txt: -e git: //github.com/CMGS/PyMySQL.git#egg=PyMySQL-dev

En MySQLdb , el método Thing2Literal no se usa si está usando una versión suficientemente reciente de MySQL, en cuyo caso se string_literal método string_literal la conexión cuando hay una conexión disponible.

Necesitará parchear pymysql para que haga lo mismo y le permita usar el método de conexión.

Contexto

Este método se utiliza para escapar de las sentencias de SQL. Mantenerse al margen, por lo tanto, tiene problemas de seguridad que debe tener en cuenta.

La razón por la que desea utilizar el método de conexión es el conjunto de caracteres, que desempeña un papel en el escape.

Arreglar el ImportError

Este es bastante sencillo, solo necesitas implementar un método Thing2Literal ficticio en pymysql.converters . Nunca lo llamaremos, así que no nos importa:

 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 en tiempo de ejecución cuando hay una conexión disponible

En pymysql.connections.Connection , agregue: import pymysql.converters

Al final de pymysql.connections.Connection.__init__ , agregue lo siguiente:

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

Y al final de pymysql.connections.Connection.__del__ , agregue el reverso:

 pymysql.converters.Thing2Literal = pymysql.converters._Thing2Literal 

Podemos descartar el argumento d porque es un diccionario de conversiones existentes, que ya están disponibles para el método Connection.escape .

Advertencias

Hay una buena posibilidad de que esto se rompa y exponga los problemas de seguridad.
Además, estoy bastante seguro de que se romperá gravemente si tienes varias conexiones activas que usan diferentes conjuntos de caracteres.


Es posible que deba jugar un poco con Django también para asegurarse de que use su versión de parche de mono cuando esté disponible, es decir, reemplazar from MySQLdb.converters import Thing2Literal con algo que aún vincule el nombre Thing2Literal con el módulo.

Por supuesto, puede lograr el mismo efecto sin aplicar parches a django y hacer que la función _Thing2Literal más inteligente.