views:

1381

answers:

7

Hi gents, as I usually don't do the up front design of my models in Django projects I end up modifying the models a lot and thus deleting my test database every time (because "syncdb" won't ever alter the tables automatically for you). Below lies my workflow and I'd like to hear about yours. Any thoughts welcome..

  1. Modify the model.
  2. Delete the test database. (always a simple sqlite database for me.)
  3. Run "syncdb".
  4. Generate some test data via code.
  5. goto 1.

A secondary question regarding this.. In case your workflow is like above, how do you execute the 4. step? Do you generate the test data manually or is there a proper hook point in Django apps where you can inject the test-data-generating-code at server startup?\

TIA.

+15  A: 

Steps 2 & 3 can be done in one step:

manage.py reset appname

Step 4 is most easily managed, from my understanding, by using fixtures

Harper Shelby
+9  A: 

This is a job for Django's fixtures. They are convenient because they are database independent and the test harness (and manage.py) have built-in support for them.

To use them:

  1. Set up your data in your app (call it "foo") using the admin tool
  2. Create a fixtures directory in your "foo" app directory
  3. Type: python manage.py dumpdata --indent=4 foo > foo/fixtures/foo.json

Now, after your syncdb stage, you just type:

 python manage.py loaddata foo.json

And your data will be re-created.

If you want them in a test case:

class FooTests(TestCase):
    fixtures = ['foo.json']

Note that you will have to recreate or manually update your fixtures if your schema changes drastically.

You can read more about fixtures in the django docs for Fixture Loading

Matthew Christensen
Don't forget `manage.py dumpdata app >app.json` to backup what you have
S.Lott
S. Lott -- unless I'm misunderstanding you isn't that covered by my step 3?
Matthew Christensen
+9  A: 

Here's what we do.

  1. Apps are named with a Schema version number. appa_2, appb_1, etc.

  2. Minor changes don't change the number.

  3. Major changes increment the number. Syncdb works. And a "data migration" script can be written.

    def migrate_appa_2_to_3():
        for a in appa_2.SomeThing.objects.all():
            appa_3.AnotherThing.create( a.this, a.that )
            appa_3.NewThing.create( a.another, a.yetAnother )
        for b in ...
    

The point is that drop and recreate isn't always appropriate. It's sometimes helpful to move data form the old model to the new model without rebuilding from scratch.

S.Lott
That's a clever approach.
Matthew Christensen
@Matthew Christensen: Thanks, but I prefer "lazy" to "clever". I like to minimize disruption and have a fall-back with minimal or no "thinking".
S.Lott
muhuk
Also do you keep prior version in INSTALLED_APPS?
muhuk
@muhunk: we replace settings and urls.py as needed. And yes, the prior version is laying around for a while until we're sure we'll never go back.
S.Lott
@S.Lott: it's muhuk, not muhunk. I'd love to learn the details of this method. I think this would be a great article.
muhuk
@muhuk: apologies. Worse, there's no easy way to edit comments except by deleting them.
S.Lott
http://homepage.mac.com/s_lott/iblog/architecture/C20070522153704/E20080806062156/index.html
S.Lott
@S.Lott: great article. Thanks for sharing.
muhuk
+2  A: 

To add to Matthew's response, I often also use custom SQL to provide initial data as documented here.

Django just looks for files in <app>/sql/<modelname>.sql and runs them after creating tables during syncdb or sqlreset. I use custom SQL when I need to do something like populate my Django tables from other non-Django database tables.

davidavr
+1  A: 

Personally my development db is for a project I'm working on right now is rather large, so I use dmigrations to create db migration scripts to modify the db (rather than wiping out the db everytime like I did in the beginning).

Edit: Actually, I'm using South now :-)

dgrant
A: 

Thanks for all the answers!

I've also found django-evolution that could come handy in this matter.

utku_karatas
+7  A: 

South is the coolest.

Though good ol' reset works best when data doesn't matter.

http://south.aeracode.org/

Antonius Common