views:

68

answers:

4

I'm new to python and django, and when following the Django Book I learned about the command 'python manage.py syncdb' which generated database tables for me. In development environment I use sqlite in memory database, so it is automatically erased everytime I restart the server. So how do I script this 'syncdb' command?(Should that be done inside the 'settings.py' file?)

CLARIFICATION

The OP is using an in-memory database, which needs to be initialized at the start of any process working with Django models defined against that database. What is the best way to ensure that the database is initialized (once per process start). This would be for running tests, or running a server, either via manage.py runserver or via a webserver process (such as with WSGI or mod_python).

+1  A: 

Update

I added a script called run.sh in the project's root directory. This worked for me with an SQLite database:

#!/usr/bin/python
from django.core.management import call_command
call_command('syncdb')
call_command('runserver')

Original Answer

I am not sure I understand what you mean by "scripting the syncdb command". You usually execute python manage.py syncdb from the command line. This is usually done after adding new models. In case you want to you easily accomplish this using a simple shell script. I don't see any reason to place (or invoke) syncdb from within settings.py.

Could you add more details to your question? Add context and explain what exactly are you trying to get done?

Manoj Govindan
I'm hoping to invoke this 'syncdb'command as any other python method, and place the invocation at settings.py, so everytime I start the app it automatically creates the database
Thiado de Arruda
Got it. I am not convinced that `settings.py` is the best place to keep it though. We can agree to disagree on that :)
Manoj Govindan
Do you have any other suggestion? I'm completely new to python. As Craig Trader stated, the invocation for 'syncdb' must happen inside the same process, so I guess that leaves shell scripts out of question.
Thiado de Arruda
Found a mechanism to call `syncdb` through the API. Updated answer. No better ideas about where to place it yet :(
Manoj Govindan
Since Daniel answered first credits goes to him, but +1 for your help anyway, thanks.
Thiado de Arruda
+1  A: 

You could create a new script that you call instead of manage.py that calls manage.py:

from subprocess import call
call(["python", "manage.py", "syncdb"])
call(["python", "manage.py", "runserver"])

If you don't need to add an admin you could change the second line like this:

call(["python", "manage.py", "syncdb", "--noinput"])

I'm assuming that what you're trying to do is create your db and then start your server with one command every time.

jfenwick
I was hoping to access 'syncdb' as some kind of python API, but that is ok.
Thiado de Arruda
This probably won't work for an in-memory database, since each `call` is invoking a separate process, which would have its own in-memory database.
Craig Trader
Yes, you are right. That probably leaves bash scripts out of question.
Thiado de Arruda
+3  A: 

All Django management commands can be accessed programmatically:

from django.core.management import call_command
call_command('syncdb', interactive=True)

Ideally you'd use a pre-init signal on runserver to activate this, but such a signal doesn't exist. So, actually, the way I'd handle this if I were you would be to create a custom management command, like runserver_newdb, and execute this inside it:

from django.core.management import call_command
call_command('syncdb', interactive=True)
call_command('runserver')

See the documentation for more information on writing custom management commands.

Daniel
+2  A: 

As suggested by this question, you can use middleware for you startup code (django docs here). For example (untested):

startup.py

from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
from django.core.management import call_command

class StartupMiddleware(object):
    def __init__(self):
        # The following db settings name is django 1.2.  django < 1.2 will use settings.DATABASE_NAME
        if settings.DATABASES['default']['NAME'] == ':memory:':
            call_command('syncdb', interactive=False)

        raise MiddlewareNotUsed('Startup complete')

and in your settings.py:

 MIDDLEWARE_CLASSES = (
     'your_project.middleware.startup.StartupMiddleware',

     # Existing middleware classes here
 )
sdolan
+1, I really like this solution, since it just happens "automagically", and doesn't require special scripts to start.
Craig Trader
Really nice solution
Thiado de Arruda