Wednesday, October 31, 2012

Django/South/MySQL bug

Hi all

I've just run into a slight problem with Django 1.4.1, south 0.7.6 and
py-MySQLdb 1.2.3.

In the fix for Django bug #14091, Django will now always look at
cursor._last_executed in order to get details of the last query
executed, which I guess is for managing connection.queries in debug
mode. However, it does not check for existence of this attribute,
which will only exist if you have already executed a query from my
reading of py-MySQLdb.

cursor._last_executed is an undocumented 'private' part of py-MySQLdb.

For some reason, trying to issue a raw DB query in a south migration
causes Django to die looking at that attribute. Either using south's
"db.execute", or using "from django.db import connection;
c=connection.cursor(); c.execute(..)" as described in the Django
manual results in the same back trace.

This issue only came about because I needed to do a south data
migration that could not efficiently be handled in the ORM. Using the
ORM - either Django's or South's - in the migration works fine. I also
tried issueing a query through the ORM first to attempt to cause the
attribute to be set, but this also fails.

The migration is straightforward, it is adding a hash algorithm so
that we can move back closer to Django's stock auth stack:

def forwards(self, orm):
from django.db import connection
c = connection.cursor()
c.execute(
"""
UPDATE auth_user SET password = 'customsha512$' + password
WHERE password != '!' AND password != '' AND password not like '%$%'
""")

The traceback looks like this:

Traceback (most recent call last):
File "manage.py", line 9, in <module>
execute_from_command_line(sys.argv)
File "lib/django/core/management/__init__.py", line 443, in
execute_from_command_line
utility.execute()
File "lib/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "lib/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
File "lib/django/core/management/base.py", line 232, in execute
output = self.handle(*args, **options)
File "lib/south/management/commands/migrate.py", line 108, in handle
ignore_ghosts = ignore_ghosts,
File "lib/south/migration/__init__.py", line 213, in migrate_app
success = migrator.migrate_many(target, workplan, database)
File "lib/south/migration/migrators.py", line 235, in migrate_many
result = migrator.__class__.migrate_many(migrator, target,
migrations, database)
File "lib/south/migration/migrators.py", line 310, in migrate_many
result = self.migrate(migration, database)
File "lib/south/migration/migrators.py", line 133, in migrate
result = self.run(migration)
File "lib/south/migration/migrators.py", line 107, in run
return self.run_migration(migration)
File "lib/south/migration/migrators.py", line 81, in run_migration
migration_function()
File "lib/south/migration/migrators.py", line 57, in <lambda>
return (lambda: direction(orm))
File "project/idp/migrations/0049_add_mintel_pw_algo.py", line 17, in forwards
""")
File "lib/south/db/generic.py", line 273, in execute
cursor.execute(sql, params)
File "lib/django/db/backends/util.py", line 44, in execute
sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "lib/django/db/backends/mysql/base.py", line 237, in last_executed_query
return cursor._last_executed
File "lib/django/db/backends/mysql/base.py", line 144, in __getattr__
return getattr(self.cursor, attr)
AttributeError: 'Cursor' object has no attribute '_last_executed'

If I attempt to do the same operation from the shell, it works
correctly. Therefore, I think there must be something specific to
South that is happening. Any tips or hints would be greatly
appreciated!

Cheers

Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment