17

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

4 Answers 4

16

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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.
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.
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.
@S.Lott That's how we do it too.
How do you get the timestamp into your mod_python/wsgi/whatever configuration for your webserver?
|
10

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.

1 Comment

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.
3

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

2 Comments

I updated the question, there is still an error even if the settings.py is in the path.
Don't forget the init.py file in the directory that has your settings.py
0

Let's say your project directory is /opt/someProject/`

This has files like:

manage.py

Now you have you may have your sub directory anywhere, does not matter. Eg. subdirectory could be like:

/opt/someproject/dir1/dir2

Now for you to import your project settings inside /opt/someProject/dir1/dir2

You need to set your PYTHONPATH variable

export PYTHONPATH=/opt/someproject/

Now to import modules from bin

from someproject import bin

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.