12

Sometimes I want to execute a file in the context of my Django project, just as if I were using the shell, but with the convenience of using a text editor. This is mainly to try something out, or quickly prototype some functionality before putting it into a view, test, recurring task, or management command.

I know I can stick these lines at the top of my .py file and it'll run in the Django context:

import sys
sys.path.append('/location/of/projet')
from django.core.management import setup_environ
import settings
setup_environ(settings)

I thought it'd be easier to make a management command that takes on argument, a python module to run, and executes it in the Django environment. Here's the 'runmodule' command I wrote:

from django.core.management.base import BaseCommand, CommandError

class Command(BaseCommand):
    help = "Runs an arbitrary module, in the Django environment, for quick prototyping of code that's too big for the shell."

    def handle(self, *args, **options):
        if not args:
            return
        module_name = args[0]

        try:
            __import__(module_name)
        except ImportError:
            print("Unable to import module %s.  Check that is within Django's PYTHONPATH" % (module_name))

This looks like it works -- I can stick some code in a module, and pass it as an argument to this command, and it'll get executed, e.g.

python manage.py runmodule myapp.trysomethingout

which will execute myapp/trysomethingout.py. Is this the best way to do this?

LS55321
  • 883
  • 1
  • 12
  • 21

3 Answers3

9

The best way to execute a script with the correct django context is to set the DJANGO_SETTINGS_MODULE environment variable to your settings module (and appropriate PYTHONPATH if needed). In windows this usually means executing:

set DJANGO_SETTINGS_MODULE=setting 

and in bash :

export DJANGO_SETTINGS_MODULE=setting 

You can now import your models etc.

see: https://docs.djangoproject.com/en/dev/topics/settings/#designating-the-settings .

Note that in order to import the settings module, one should use from django.conf import settings. This takes into account the DJANGO_SETTINGS_MODULE instead of automatically using settings.py .

Udi
  • 29,222
  • 9
  • 96
  • 129
  • 1
    you can put it directly on your python script on your if __name__ == "__main__": with this line: os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") – OriolJ Mar 04 '15 at 10:32
2

Here's the simplest solution:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

import django
django.setup()

Be sure to include this at the top of your python file, before importing any of your models.

Alternatively, you could use the solution pointed out by @beyondfloatingpoint:

import os, sys

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
sys.path.append("mysite")
os.chdir("mysite")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
caram
  • 1,494
  • 13
  • 21
0

Best solution is provided in this article.

Hints: Make sure you are using correct path to settings module, in my case, I missed nested dirs named the same way. The best way to avoid my mistake is to use something like this template to start with.

beyondfloatingpoint
  • 1,239
  • 1
  • 14
  • 23