Wednesday, October 31, 2012

Re: Django/South/MySQL bug

Hmm, I'm not sure why issuing a query previously isn't fixing it - South just uses the same database cursors that the rest of Django uses, it's one of the few things we don't mess around with.

Surely Django has to have some code to deal with the case when there isn't that attribute already? Have you tried working out why that's not happening?

Andrew

On Wed, Oct 31, 2012 at 2:19 PM, Tom Evans <tevans.uk@googlemail.com> wrote:
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 "South Users" group.
To post to this group, send email to south-users@googlegroups.com.
To unsubscribe from this group, send email to south-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/south-users?hl=en.


--
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