Django settings.py and your database

Default Django settings are terrible. Why? Because the default convention makes it a pain to have different settings for local development and for production (or testing or staging, but you get the picture). This is true for all of 1.x and nothing is on the horizon for 2.0 will fix this. This sucks especially for database related stuff because for the most part the big difference between a production and a development installation is the database configuration.

How settings work

settings.py are just module level variables in a file. By convention this is in a file called settings.py that lives at the root of the project. However, you can call this file anything and you can put it anywhere that a python import can find it.

Because it depends on importing doing custom of complicated things with settings.py can get a bit confusing (a topic for another post). What is important about this is that you can point a given installation of django to an arbitrary settings.py by setting the environment variable DJANGO_SETTINGS_MODULE

We can use this to overcome one of the big issues with the default conventions, which is we usually need different databases in development than we do in production. Even if you are using the same database system, you’ll still need a different set of credentials and hostnames to do your development. There are several ways that your python knowledge might apply, but there is probably one sane way of doing this: multiple files and set the environment variable to the proper one.

  • Add a settings/ directory where your settings.py already is. If using python 2, don’t forget to add a __init__.py to your new directory.
  • Move your existing settings.py to settings/base.py
  • Remove the settings.pyc file if any.
  • Find the elements that will change from development to production, like DATABASES, and move them from base.py to settings/dev.py or settings/production.py</ code> or create the approriate entries for each.
  • If you use your manage.py script, update it to point to your default environment.
    if __name__ == "__main__":                          
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings.dev")

For your production environments, you’ll need to change the environment variable passed to the engine. This varies depending on which app server you are using. The contents of each file will obviously differ based on the databases you are using, but here are some examples.

settings/dev.py

                                                                    
...                                                                                                                               
DATABASES = {                                                                                                                     
    'default': {                                                                                                                  
        'ENGINE': 'django.db.backends.sqlite3',                                                                                   
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),                                                                             
    }                                                                                                                             
}                                                                                                                                 
...                                                                                                                               

settings/production.py

DATABASES = {                                                       
     'default': {                                                                                                                 
          'ENGINE': 'django.db.backends.postgresql',                                                                              
          'NAME': '$DATABASE',                                                                                                    
          'USER': '$DBUSER',                                                                                                      
          'PASSWORD': '$DBPASSWORD',                                                                                              
          'HOST': '$HOSTNAME',                                                                                                    
          'PORT': '$HOSTPORTNUMBER'                                                                                               
     }                                                                                                                            
}                                                                                                                                 

Leave a Reply

Your email address will not be published. Required fields are marked *