Python script for Django app to access models without using manage.py shell
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)
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()
I think the best way is to create your custom management command(s). Then you can call manage.py <yourcommand>
from anywhere.