15

I was very confused today.

I was trying to use my django app models in my python script.

here is my approach

import os, sys

sys.path.append("/var/www/cloudloon/horizon")
os.environ["DJANGO_SETTINGS_MODULE"] = "openstack_dashboard.settings"
from django.contrib.auth.models import User

I was confused why its giving me

ImportError: Could not import settings 'openstack_dashboard.settings' (Is it on sys.path?): cannot import name auth

Upon checking I created a a file called creds that includes

export PYTHONPATH=$PYTHONPATH:/var/www/cloudloon/horizon/; 
export DJANGO_SETTINGS_MODULE=openstack_dashboard.settings; django-admin.py shell;

and from terminal window where creds file is located, I do

source creds

and from that django-admin.py shell, I could import any of my django app models without any errors.

Why it doesn't work in my python script?

I am done with Django, What I need to do is to create a python-daemon script that will access my django app models.

I am working with in Ubuntu 12.04 that has django 1.5

As I looking for solutions, I did this:

import os, sys

sys.path.append("/var/www/cloudloon/horizon")
sys.path.append("/var/www/cloudloon/horizon/openstack_dashboard")
# os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
                          "openstack_dashboard.settings")

print os.environ["DJANGO_SETTINGS_MODULE"]
for s in sys.path:
    print s

from django.contrib.auth.models import User

heres the output: http://paste.openstack.org/show/48787/

as you can see, the directory where settings.py is located are present on my sys.path, however, It was still unable to import openstack_dashboard.settings.

Thanks everyone.

4 Answers 4

33

You need to write a custom management command, instead of doing these weird acrobatics.

Create a module called management (in other words, create a directory management and inside it create an empty __init__.py file) inside the directory of any app that you have listed in INSTALLED_APPS. So if you have myapp, you would create:

myapp
 |
 > management
 | | __init__.py
 > models.py
 > views.py

Then in the management directory, create another module commands and in it create a file which is the name of your command; for example my_command.py, like this:

myapp
 |
 > management
 | | __init__.py
 | | commands
 | | | __init__.py
 | | | my_command.py
 > models.py
 > views.py

In my_command.py, write this boilerplate code:

from django.core.management.base import BaseCommand, CommandError
from myapp.models import MyModel

class Command(BaseCommand):
    help = 'Does some magical work'

    def handle(self, *args, **options):
        """ Do your work here """
        self.stdout.write('There are {} things!'.format(MyModel.objects.count()))

Once you save the file, you'll be able to do python manage.py my_command and it will have access to all your models and settings.

If you need to run it as a daemon, Daniel Roseman wrote django-initd which does exactly that. Once you have installed it:

from django.core.management.base import CommandError
from daemon_command import DaemonCommand
from myapp.models import MyModel

class Command(DaemonCommand):
    help = 'Does some magical work'

    def loop_callback(self, *args, **options):
        """ Do your work here """
        self.stdout.write('There are {} things!'.format(MyModel.objects.count()))

Once you have that done from the github readme:

The important parts of such a process are these:

    * it comes up automatically on server startup
    * it logs errors and information to a named location, which is configurable
    * if the process dies, it restarts itself straight away 

[...]

Run the command as normal, but pass one of --start, --stop or --restart to 
work as a daemon. Otherwise, the command will run as a standard application.
Sign up to request clarification or add additional context in comments.

6 Comments

I had this as an answer previously, but the script is supposed to be a daemon, not a once off command.
It seems too difficult to implement with python-daemon.
Nice answer, didn't know about django-initd. This is how OP should do it, but I think OP has path issues.
The path issues will go away once he uses a management command.
This worked perfectly on Django 1.8. (None of the path setting and importing techniques suggested in other answers worked.)
|
11

The below script should work provided that the layout of your project (and the path to your settings file) looks like this:

/var/www/cloudloon/horizon/openstack_dashboard/settings.py

#!/usr/bin/env python
import os, sys

sys.path.append("/var/www/cloudloon/horizon")
os.environ["DJANGO_SETTINGS_MODULE"] = "openstack_dashboard.settings"
from django.contrib.auth.models import User

I believe the problem you're seeing is due to the arrangement of your project, or that you need to append another directory level to the sys.path call in the script.

Edit:

Looking at your github project, horizon and openstack_dashboard are on the same directory level. What you'd want to do is set your sys.path to one level higher:

sys.path.append("/var/www/cloudloon")

7 Comments

management command seems not a good idea for what I am trying to create. I need to create python-daemon script. Basically, to run python-daemon script, I need to run "python myscript.py run". Python management command is not good for it.
Using your code above, It gives me AttributeError: 'str' object has no attribute 'file'
@DjangoBot sorry, the setup_environ takes a module object, not a string. I've corrected the code snippet.
setup_environ seems have been deprecated since Django 1.4. DeprecationWarning: The 'setup_environ' function is deprecated, you likely need to update your 'manage.py'; please see the Django 1.4 release notes (docs.djangoproject.com/en/dev/releases/1.4)
@DjangoBot I've updated my answer, but it basically only says to check your project structure.
|
5

This worked for me:

from django.conf import settings
import myfolder.settings as app_settings

settings.configure(INSTALLED_APPS=app_settings.INSTALLED_APPS,DATABASES=app_settings.DATABASES)

import django
django.setup()

from myapp123.models import Sample
for s in Sample.objects.all():
    print(s)

Comments

1

My solution (inspired by http://blog.gabrielsaldana.org/using-django-models-in-external-python-scripts/):

import os
import sys
sys.path.append( os.path.join(os.path.dirname(__file__), 'MyDjangoProject'))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "MyDjangoProject.settings")
import django
from django.conf import settings
django.setup()

from myapp.models import MyModel
for s in MyModel.objects.all():
    print(s) 

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.