I have a django app that I've packaged according to the docs here: https://docs.djangoproject.com/en/1.5/intro/reusable-apps/
I installed the app into a virtual environment using setup.py.
./setup.py install
The app's web UI runs fine from the virtual environment. But I cannot access the custom management command with this vanilla install.
(django_grm)[grm@controller django_grm]$ python ./manage.py sync_to_graphite
Unknown command: 'sync_to_graphite'
Here's what the virtual environment looks like when the command will not execute:
(django_grm)[grm@controller django_grm]$ ll /home/grm/venv/django_grm/lib/python2.7/site-packages
total 1148
...
-rw-rw-r-- 1 grm grm 243962 Jun 19 17:11 django_grm-0.0.4-py2.7.egg
...
However, once I unzip the .egg file, the management command works as expected.
(django_grm)[grm@controller django_grm]$ cd /home/grm/venv/django_grm/lib/python2.7/site-packages
(django_grm)[grm@controller site-packages]$ unzip django_grm-0.0.4-py2.7.egg
(django_grm)[grm@controller site-packages]$ ll /home/grm/venv/django_grm/lib/python2.7/site-packages
total 1152
...
-rw-rw-r-- 1 grm grm 243962 Jun 19 17:11 django_grm-0.0.4-py2.7.egg
drwxrwxr-x 6 grm grm 4096 Jun 19 17:16 dj_grm
...
(django_grm)[grm@controller site-packages]$ cd /home/grm/django_projects/django_grm/
(django_grm)[grm@controller django_grm]$ python ./manage.py sync_to_graphite
<success>
Is this normal behaviour? It feels wonky.
I strongly suggest using pip
instead of setup.py
. It tends to do a much better job of installing packages as well as managing them.
Once you have your virtual environment in place, it would be:
$ . env/bin/activate
$ pip install [APP_NAME]
This installs a non-zipped version of the app in the virtual environment.
If the app is a zip from somewhere, you can still use pip
$ pip install http://[URL_TO_ZIP]
Let's take a look at the part of the source that loads management commands:
def find_commands(management_dir):
"""
Given a path to a management directory, returns a list of all the command
names that are available.
Returns an empty list if no commands are defined.
"""
command_dir = os.path.join(management_dir, 'commands')
try:
return [f[:-3] for f in os.listdir(command_dir)
if not f.startswith('_') and f.endswith('.py')]
except OSError:
return []
which is called by:
# Find and load the management module for each installed app.
for app_name in apps:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
for name in find_commands(path)]))
except ImportError:
pass # No management module - ignore this app
So, yeah, Django doesn't support apps installed in a zipped file, at least here; it wants an explicit commands
directory inside management_dir
.
As @tghw notes, installing via pip
will keep the package in a directory instead of zipping it. You can also (and probably should also) set zip_safe=False
in your setup()
command; this will stop setuptools/distribute/etc from trying to zip up your package no matter how you install it.
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