Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django syncdb not running custom SQL

I'm trying to get my app to run some custom SQL on syncdb with the official method of placing some INSERT statements into /sql/.sql

Now, when I run "manage.py sqlall ", all the SQL I want run is there.

However, after running syncdb, the data I want is nowhere to be found in the database! Am I missing something?

EDIT: The app I want to make the inserts for is using South migrations, and this is maybe why the initial SQL is skipped. Does anyone know how I can force it to run the SQL after migration, perhaps?

like image 359
elsurudo Avatar asked Feb 05 '12 01:02

elsurudo


1 Answers

Initial data sql doesn't get run for South-managed applications. From what I understood this is by design, though I couldn't find any formal proof of that, except this mailing list post.

To achieve the same behavior you can create a migration and convert your SQL to Python. This is how I did it for installing a view:

Create and edit the migration:

$ python manage.py schemamigration app1 install_foo_view --empty
$ vim app1/migrations/*_install_foo_view.py

Here's the migration itself:

from south.db import db
from south.v2 import SchemaMigration

class Migration(SchemaMigration):

    def forwards(self, orm):
        db.execute("CREATE VIEW app1_foo AS SELECT col1, col2 FROM app1_bar")

    def backwards(self, orm):
        db.execute("DROP VIEW app1_foo")

    # autogenerated models attibute goes here

    complete_apps = ['app1']

For data migrations the flow is similar:

$ python manage.py datamigration app1 install_bars
$ vim app1/migrations/*_install_bars.py

Here's the migration itself:

from south.db import db
from south.v2 import DataMigration

class Migration(DataMigration):

    def forwards(self, orm):
        orm.Bar.objects.create(col1='val1', col2='val2')

    def backwards(self, orm):
        orm.Bar.objects.filter(col1='val1', col2='val2').delete()

    # autogenerated models attibute goes here

    complete_apps = ['app1']

The official South doc for data fixtures is broken:

  1. It doesn't scale well with respect to schema changes.

    You should copy and adjust the fixture file each time you change the Bar model fields. So you would end up with "my_fixture_v1.json", "my_fixture_v2.json" and so on.

    Otherwise, if you don't keep versioning them and just keep the latest version, there will be mismatches between previous versions of model and the fixture and you won't be able to navigate migrations back and forth.

  2. It doesn't support backwards migration.

The suggested approach takes care of both of these issues:

  1. Since you use orm.Bar you have the set of fields that is applicable to Bar right at that point in history. You won't get any missing or extra fields.
  2. There's no need to keep copying anything with Bar changes.
  3. It is possible to migrate backwards.

    Note that filter().delete() combination is used instead of get().delete(). This way you won't delete the Bars that has been changed by user, neither you fail with Bar.DoesNotExist when not finding them.

like image 187
Ihor Kaharlichenko Avatar answered Oct 02 '22 06:10

Ihor Kaharlichenko