I'm writing a script to import some model objects into the database my django application uses. In the past I've solved this by running ./manage.py shell
and then import myscript
. I'm sure there's a better way. I'd like to be able to call a script from anywhere on my HD using python scriptname.py
, and in the first few lines of that script it would do whatever imports / other operations necessary so that it can access model objects and behave as though it was run using manage.py shell
.
What do I need to add to my script to achieve this?
EDIT:
Based on @Melug's answer, with addition of dynamically setting Python path to address the 'anywhere on my HD' part of the question:
import sys
sys.path.append('c:\\my_projec_src_folder')
from myproject import settings
from django.core.management import setup_environ
setup_environ(settings)
The reason I use management commands is because Django puts a bunch of stuff on the Python path when it starts up (such as django ) and using a management command harnesses this. python manage.py shell starts up a regular version of the python interrupter but with the added environment.
When you run python manage.py shell you run a python (or IPython) interpreter but inside it load all your Django project configurations so you can execute commands against the database or any other resources that are available in your Django project.
Since Django 1.4 you should avoid using setup_environ(settings)
(post by Melug) because it is deprecated. Use the following instead and you will be able to access your model
import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project_name.settings") # your imports, e.g. Django models from your_project_name.models import Location # From now onwards start your script..
Here is an example to access and modify your model:
if __name__ == '__main__': # e.g. add a new location l = Location() l.name = 'Berlin' l.save() # this is an example to access your model locations = Location.objects.all() print locations # e.g. delete the location berlin = Location.objects.filter(name='Berlin') print berlin berlin.delete()
Example model:
class Location(models.Model): name = models.CharField(max_length=100)
To get models loaded too, I had to combine this with this answer, otherwise I get django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
import django
django.setup()
As an extra, I add this to the __init__.py
of my django projects, it will automatically discover the app name so it is copy/paste-able:
import os
def setup():
module = os.path.split(os.path.dirname(__file__))[-1]
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{}.settings".format(module))
import django
django.setup()
Then I can just do:
from <app> import setup
setup()
For Django version 1.9 or later you can use this:
import sys
import os
import django
sys.path.append('your_project_directory')
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_project.settings'
django.setup()
from yourapp.models import your_model
so you can use object as same django object:
from myapp.models. import Locations
all_locations = Locations.object.all()
first_location = Locations.object.get(id=1)
print first_location.name()
first_location.save()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With