Ticket #138 (closed defect: invalid)

Opened 5 years ago

Last modified 5 years ago

forward() and backwards() run twice

Reported by: derek73@… Owned by: andrew
Priority: critical Milestone:
Component: migrations Version: 0.5
Keywords: Cc:

Description

I was trying to create a migration that populated a new model with data from an old model and I kept getting duplicate key errors. Took me a while to figure out but putting a print statement in the migration indicates the forward() and backwards() methods actually run twice.

class Migration:
    def forwards(self, orm):
        print "running forward"
    def backwards(self, orm):
        print "running backwards"
$ ./manage migrate app
running forward
running forward
$ ./manage migrate app zero
running backwards
running backwards

Change History

comment:1 Changed 5 years ago by andrew

  • Status changed from new to closed
  • Resolution set to invalid

Yes, because you're running MySQL and so it's doing a dry run before the actual run. If you look in the tutorial, you'll see that anything that doesn't use the database API to do manipulation needs to be wrapped in 'if not db.dry_run:'.

However, South's designed to catch most dry-run problems like this. What did your code look like?

comment:2 Changed 5 years ago by derek73@…

muchas gracias

i was doing:

def forwards(self, orm):
    from app.models import OldModel, NewModel
    for obj in OldModel.objects.all().iterator():
        NewModel.objects.create(attr=obj.attr1, attr2=obj.attr2)

i looked through the docs for something like db.execute() but to wrap code in, but didn't find anything. i didn't look too hard though. :) a db method probably doesn't make sense anyway.

i guess you can't really have it only do the db methods on a dry run or it's not a real dry run. not sure what the best solution is either.

maybe though the expected behavior would be to not run the code parts, i.e. non db.methods(), on a dry run. but I don't think I would expect that your migration tool could perform a "dry run" of my code without providing some sort of mechanism to make my code not have any effect. perhaps just that the migration file imports without errors is good enough for a dry run for the code parts.

(i didn't even know it was doing a dry run, makes sense now that you told me but when my code was running twice i couldn't think of any reason why. the method name is forward, not forward_twice(). :) Maybe you could run the code parts only when an option is passed to the migration script.)

if not db.dry_run works for me though. :)

comment:3 Changed 5 years ago by andrew

Ah, I see the problem. When you use the ORM you're supposed to use the frozen version - see the third tutorial section. Those special models _do_ wig you're running in a dry run.

Note: See TracTickets for help on using tickets.