8

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?

elsurudo
  • 3,579
  • 2
  • 31
  • 48

2 Answers2

3

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.

Ihor Kaharlichenko
  • 5,944
  • 1
  • 26
  • 32
  • Thanks for the detailed answer. Unfortunately, I asked this so long ago, and haven't used Django since, so I am unable to verify whether this is "correct". If someone finds this solves the issue, please let me know so I can accurately mark this as answered. – elsurudo Jan 23 '14 at 12:03
  • You're welcome :) The code I posted is exactly the one I use in production, just the model names are changed. Hope it would help somebody. – Ihor Kaharlichenko Jan 23 '14 at 12:31
-1

I am not exactly sure what you are doing, but if you are wanting to prepopulate the database you need to use fixtures.

https://docs.djangoproject.com/en/1.3/howto/initial-data/

Buddy Lindsey
  • 3,560
  • 6
  • 30
  • 42
  • Look just below that: https://docs.djangoproject.com/en/1.3/howto/initial-data/#providing-initial-sql-data I agree that fixtures are probably a better idea in general since they would work with all DBs, but I already have the INSERT statements I want from another database, so SQL is what I want here. – elsurudo Feb 05 '12 at 11:50
  • is your sql folder in your app folder or in the root of the project? – Buddy Lindsey Feb 05 '12 at 18:22
  • It's in apps//sql, so in my app folder. Like I said, "squall" finds it perfectly. I think it may not being run because that specific app uses South migrations. I'm not sure how to get both of them to work together... – elsurudo Feb 06 '12 at 11:50
  • Going through one of my projects it looks like I did go through the hassle of converting my sql statements to json. However, i did find this maybe it might help you. http://stackoverflow.com/questions/2412328/how-to-load-sql-fixture-in-django-for-user-model – Buddy Lindsey Feb 06 '12 at 21:00