tags:

views:

2095

answers:

3

I created a sub-directory of my Django project called bin where I want to put all command-line run Python scripts. Some of these scripts need to import my Django project settings.py file that is in a parent directory of bin.

How can I import the settings.py file from a sub-directory of the project?

The code that I use in my command-line script to set into the "Django context" of the project is:

from django.core.management import setup_environ
import settings
setup_environ(settings)

This works fine if the script is in the root directory of my project.

I tried the following two hacks to import the settings.py file and then setup the project:

import os
os.chdir("..")

import sys
sys.path = [str(sys.path[0]) + "/../"] + sys.path

The cruel hack can import settings.py, but then I get the error:

project_module = __import__(project_name, {}, {}, [''])
ValueError: Empty module name
A: 

Add the parent directory to your path:

import sys
sys.path.append('../')
import settings

Update from comments:

Don't forget the __init__.py file in the directory that has your settings.py – S.Lott

jcoon
I updated the question, there is still an error even if the settings.py is in the path.
MikeN
Don't forget the __init__.py file in the directory that has your settings.py
S.Lott
There is an __init__.py file, that doesn't work.
MikeN
+4  A: 

I think your approach may be over-complicating something that Django 1.x provides for you. As long as your project is in your python path, you can set the environment variable DJANGO_SETTINGS_MODULE at the top of your script like so:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'

In your command line script where you need to read your settings, simply import the settings module from 'django.conf' as you would do in your application code:

from django.conf import settings

And presto, you have your settings and a Django-enabled environment for your script.

I personally prefer to set my DJANGO_SETTINGS_MODULE using '/usr/bin/env' in a bash script called 'proj_env' so I don't have to repeat it

#!/bin/bash

proj_env="DJANGO_SETTINGS_MODULE=myproject.settings"

/usr/bin/env $proj_env ${*}

With this, now I can run any python script with my Django application in context:

proj_env python -m 'myproject.bin.myscript'

If you use virtualenv, this also gives you a good place to source the activate script.

etc. etc.

Joe Holloway
So the directory above your project directory has to be in the Python path? And the project directory holding settings.py has to be in the same directory name all the time? My dev. project name is different than my production name, the directory name has a timestamp on it in production.
MikeN
We put our settings in /var/this and our apps in /opt/that. Our PYTHONPATH is "/var/this:/opt/that". The settings are separate from the apps.
S.Lott
In the example above the 'myproject' package has to be on the python path, but that would already have to be there for Django to find it too. My approach would work in your dev environment, but not sure what adjustments to make to deal with a timestamp.
Joe Holloway
@S.Lott That's how we do it too.
Joe Holloway
How do you get the timestamp into your mod_python/wsgi/whatever configuration for your webserver?
Joe Holloway
@holloway7: What timestamp are you talking about?
S.Lott
@S.Lott That was for @MikeN, he said his "directory name has a timestamp on it in production" which indicates he's trying to invent a generic solution that avoids the need to know the path to his settings.py. My question about his webserver config should shed some light on what the heck that is.
Joe Holloway
+5  A: 

This is going one level up from your question, but probably the best solution here is to implement your scripts as custom manage.py (django-admin.py) commands. This gives you all of Django's functionality (including settings) for free with no ugly path-hacking, as well as command-line niceties like options parsing. I've never seen a good reason to write Django-related command-line scripts any other way.

Carl Meyer
Thanks for the answer, I was too lazy to lookup adding management commands before, but it is just what I wanted to do and helps keep all of my scripts in one place.
MikeN