Crosstips.org

My fun Crossword solver project. Crosstips.org & Krysstips.se

Kung Fu

Fujian White Crane Kung Fu

Fry-IT

Fry-IT is the company I work for

Photos

Photoalbum, both old and new.

Zope

What I have and am doing with Zope

Receptsamlingen

In Swedish only. About my "Collection of Recipes" website.

Contact me

My contact details and how to contact me.

 

KungFuPeople.com
Do you train Kung Fu?
Or know someone who does?
Then check out KungFuPeople.com


Mobile version of this page Mobile version of this page


 

Migrating with South on a field that uses auto_now_add=True


migration, auto_now_add=true, modify_date , datetimefield, auto_now=true, south, auto_now, startmigration, add_column, orm, auto_now_add

16th of December 2009

I have a Django model that looks something like this:

 class MyModel(models.Model):
    modify_date = models.DateTimeField(auto_now=True)
    ...

Retroactively now I wanted to add a field called add_date which uses the auto_now_add=True trick. The migration used in this project is South which is great but doesn't work very well with the auto_now_add=True because the field doesn't have a straight forward default. So, first I changed the field to this:

 class MyModel(models.Model):
    modify_date = models.DateTimeField(auto_now=True)
    add_date = models.DateTimeField(auto_now_add=True, null=True)
    ...

Notice the null=True which is important. Then I used startmigration to generate the code for the forward and backward to which I added a this stuff:

 class Migration:

    def forwards(self, orm):

        db.add_column('myapp_mymodel', 'add_date', orm['myapp.mymodel:add_date'])
        for each in MyModel.objects.all():
            # since MyModel is referenced elsewhere I can work out the oldest date
            oldest_date = get_oldest_related_date(each, 
                               default=each.modify_date)
            each.add_date = oldest_date
            each.save()

That way all old records will have the date (not entirely accurate but good enough) and all new records will automatically get a date. Is there a better way? I bet, but I don't know how to do it.



Comment

Carl - 17th December 2009  [«« Reply to this]
I think the better way is to avoid using auto_now_add in the first place, and instead use the more explicit "default=datetime.datetime.now" (or utcnow). Then South can handle it without assistance.
Nirvisual - 17th December 2009   [«« Reply to this]
Carl: Using "default=datetime.datetime.now" doesn't work with South migrations. It causes South to evaluate the expression, hard-coding today's date in the migration. Then every time you run the migration you get that date, regardless of the actual date.
Carl - 17th December 2009   [«« Reply to this]
Hmm, apparently South 0.6 doesn't actually handle dynamic defaults well at all; I was basing this comment off the last time I did it, with 0.5, when it worked fine. So never mind ;-)

Though apparently the next version of South will handle it well again (by ignoring defaults entirely): http://south.aeracode.org/ticket/273
 
Name:
Email:
hide my email address.

Your email address will be encoded to prevent email-extraction spiders from reading it so you won't get spammed if you decide to show your email address.