One of the great things about Python is the interactive shell. This allows you to try things out interactively before actually writing any permanent code.
I have been noticing how annoying it was to actually play with my Django code in the interactive shell because everytime you wanted to use a model you had to import it first. And what is worse, if you make some changes to the model you’re using, they won’t show up until you quit the shell, start it, and reimport the model again.
So I started snooping around the code behind the “./manage.py shell” command to see if there was a way to autoload all my Django models everytime I started the shell. I noticed that Django uses IPython by default if it is installed. So I installed IPython which offers a lot of helpful shortcuts and features for working with Python in an interpreter. I would definitely recommend checking it out if you use the Python interpreter a lot.
You can have IPython run a script everytime it starts up, so here’s how to get it to autoload all your Django models everytime you use “./manage.py shell”.
Create a python script with the following code. I just called it ipythonrc.py and put it in the root of my Django project.
from django.db.models.loading import get_models
for m in get_models():
exec "from %s import %s" % (m.__module__, m.__name__)
Then edit ~/.ipython/ipythonrc and look for the section called “Section: Python files to load and execute” around line 566. Simply put the name of the file you created above in there like this:
execfile ipythonrc.py
That’s all there is to it. You should be able to run “./manage.py shell” and have immediate access to all your models.
The use of “exec” is a bit ugly; there are two other ways I can think of which accomplish the same without it:
1. Use Python’s built-in “__import__()” function to handle the import dynamically (__import__ can import based on strings).
2. Do something more like this:
for m in get_models():
globals()[m.__name__] = m
Though if you have two models in different apps with the same class name, you’ll only get one of them in the global scope.
Comment by James Bennett — January 9, 2008 @ 2:49 pm
Thanks James,
I’m kind of new at Python so I wasn’t sure what the best way to do it. This was my stab at it but I’m sure there are better ways like you mentioned.
Wonder why the test command doesn’t already do it — when I looked at the code it seemed like it did at one point?
Comment by Peter Sheats — January 9, 2008 @ 3:19 pm
This is what i needed. Thanks.
Comment by Bulkan Evcimen — January 9, 2008 @ 5:40 pm
Note: you can also add the python code directly to ipy_user_conf.py.
It would also be possible to create ipy_profile_django.py, in which case it would be executed every time you start ipython with
“ipython -p django”
Comment by Ville Vainio — January 10, 2008 @ 9:25 am
A slight clarification – instead of ‘exec’, if you are using ipy_user_conf.py, you would execute ‘ip.ex(“from %s import %s” % (m.__module__, m.__name__)’ to execute it in IPython user namespace.
Comment by Ville Vainio — January 10, 2008 @ 9:27 am
Thanks for the tip Peter.
If you follow Ville’s suggestion to place this code in ipy_user_conf.py, it might be handy to wrap the get_models import in a try/except so ipython doesn’t complain when started without manage.py shell (since django will raise an ImportError when the settings haven’t been configured).
To wit…
try:
from django.db.models.loading import get_models
except ImportError:
from django.conf import settings
settings.configure()
from django.db.models.loading import get_models
for m in get_models():
ip.ex(“from %s import %s” % (m.__module__, m.__name__))
Comment by Don Spaulding — June 26, 2008 @ 12:28 pm
I would like to point out that by default IPython will try to load the RC file from the current directory first — thus if you have an “ipythonrc” file in the same directory as your “manage.py”, you’re all set. You need to remember, however, that you need to include the default ipythonrc still…
Here is an example of a working “ipythonrc” from one of my projects:
include ~/.ipython/ipythonrc
execute from django.contrib.auth.models import User
execute from core.models import *
Comment by Artem Egorkine — September 17, 2008 @ 2:46 am
Thanks, this works perfect, but one thing I wasn’t able to handle is the automatic reload once the source has changed – as it is done by manage.py runserver.
Doeas anybody have an idea how to achieve this?
Comment by Günter Walser — May 15, 2009 @ 9:37 am